HeapAnalysesClient.js (11126B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const DevToolsUtils = require("resource://devtools/shared/DevToolsUtils.js"); 8 const lazy = {}; 9 ChromeUtils.defineESModuleGetters(lazy, { 10 DevToolsWorker: "resource://devtools/shared/worker/worker.sys.mjs", 11 }); 12 13 const WORKER_URL = 14 "resource://devtools/shared/heapsnapshot/HeapAnalyses.worker.js"; 15 var workerCounter = 0; 16 17 /** 18 * A HeapAnalysesClient instance provides a developer-friendly interface for 19 * interacting with a HeapAnalysesWorker. This enables users to be ignorant of 20 * the message passing protocol used to communicate with the worker. The 21 * HeapAnalysesClient owns the worker, and terminating the worker is done by 22 * terminating the client (see the `destroy` method). 23 */ 24 const HeapAnalysesClient = (module.exports = function () { 25 this._worker = new lazy.DevToolsWorker(WORKER_URL, { 26 name: `HeapAnalyses-${workerCounter++}`, 27 verbose: DevToolsUtils.dumpv.wantVerbose, 28 }); 29 }); 30 31 /** 32 * Destroy the worker, causing it to release its resources (such as heap 33 * snapshots it has deserialized and read into memory). The client is no longer 34 * usable after calling this method. 35 */ 36 HeapAnalysesClient.prototype.destroy = function () { 37 this._worker.destroy(); 38 this._worker = null; 39 }; 40 41 /** 42 * Tell the worker to read into memory the heap snapshot at the given file 43 * path. This is a prerequisite for asking the worker to perform various 44 * analyses on a heap snapshot. 45 * 46 * @param {string} snapshotFilePath 47 * 48 * @returns Promise 49 * The promise is fulfilled if the heap snapshot is successfully 50 * deserialized and read into memory. The promise is rejected if that 51 * does not happen, eg due to a bad file path or malformed heap 52 * snapshot file. 53 */ 54 HeapAnalysesClient.prototype.readHeapSnapshot = function (snapshotFilePath) { 55 return this._worker.performTask("readHeapSnapshot", { snapshotFilePath }); 56 }; 57 58 /** 59 * Tell the worker to delete all references to the snapshot and dominator trees 60 * linked to the provided snapshot file path. 61 * 62 * @param {string} snapshotFilePath 63 * @return Promise<undefined> 64 */ 65 HeapAnalysesClient.prototype.deleteHeapSnapshot = function (snapshotFilePath) { 66 return this._worker.performTask("deleteHeapSnapshot", { snapshotFilePath }); 67 }; 68 69 /** 70 * Request the creation time given a snapshot file path. Returns `null` 71 * if snapshot does not exist. 72 * 73 * @param {string} snapshotFilePath 74 * The path to the snapshot. 75 * @return {number?} 76 * The unix timestamp of the creation time of the snapshot, or null if 77 * snapshot does not exist. 78 */ 79 HeapAnalysesClient.prototype.getCreationTime = function (snapshotFilePath) { 80 return this._worker.performTask("getCreationTime", snapshotFilePath); 81 }; 82 83 /*** Censuses *****************************************************************/ 84 85 /** 86 * Ask the worker to perform a census analysis on the heap snapshot with the 87 * given path. The heap snapshot at the given path must have already been read 88 * into memory by the worker (see `readHeapSnapshot`). 89 * 90 * @param {string} snapshotFilePath 91 * 92 * @param {object} censusOptions 93 * A structured-cloneable object specifying the requested census's 94 * breakdown. See the "takeCensus" section of 95 * `js/src/doc/Debugger/Debugger.Memory.md` for detailed documentation. 96 * 97 * @param {object} requestOptions 98 * An object specifying options of this worker request. 99 * - {Boolean} asTreeNode 100 * Whether or not the census is returned as a CensusTreeNode, 101 * or just a breakdown report. Defaults to false. 102 * @see `devtools/shared/heapsnapshot/census-tree-node.js` 103 * - {Boolean} asInvertedTreeNode 104 * Whether or not the census is returned as an inverted 105 * CensusTreeNode. Defaults to false. 106 * - {String} filter 107 * A filter string to prune the resulting tree with. Only applies if 108 * either asTreeNode or asInvertedTreeNode is true. 109 * 110 * @returns Promise<Object> 111 * An object with the following properties: 112 * - report: 113 * The report generated by the given census breakdown, or a 114 * CensusTreeNode generated by the given census breakdown if 115 * `asTreeNode` is true. 116 * - parentMap: 117 * The result of calling CensusUtils.createParentMap on the generated 118 * report. Only exists if asTreeNode or asInvertedTreeNode are set. 119 */ 120 HeapAnalysesClient.prototype.takeCensus = function ( 121 snapshotFilePath, 122 censusOptions, 123 requestOptions = {} 124 ) { 125 return this._worker.performTask("takeCensus", { 126 snapshotFilePath, 127 censusOptions, 128 requestOptions, 129 }); 130 }; 131 132 /** 133 * Get the individual nodes that correspond to the given census report leaf 134 * indices. 135 * 136 * @param {object} opts 137 * An object with the following properties: 138 * - {DominatorTreeId} dominatorTreeId: The id of the dominator tree. 139 * - {Set<Number>} indices: The indices of the census report leaves we 140 * would like to get the individuals for. 141 * - {Object} censusBreakdown: The breakdown used to generate the census. 142 * - {Object} labelBreakdown: The breakdown we would like to use when 143 * labeling the resulting nodes. 144 * - {Number} maxRetainingPaths: The maximum number of retaining paths to 145 * compute for each node. 146 * - {Number} maxIndividuals: The maximum number of individual nodes to 147 * return. 148 * 149 * @returns {Promise<object>} 150 * A promise of an object with the following properties: 151 * - {Array<DominatorTreeNode>} nodes: An array of `DominatorTreeNode`s 152 * with their shortest paths attached, and without any dominator tree 153 * child/parent information attached. The results are sorted by 154 * retained size. 155 */ 156 HeapAnalysesClient.prototype.getCensusIndividuals = function (opts) { 157 return this._worker.performTask("getCensusIndividuals", opts); 158 }; 159 160 /** 161 * Request that the worker take a census on the heap snapshots with the given 162 * paths and then return the difference between them. Both heap snapshots must 163 * have already been read into memory by the worker (see `readHeapSnapshot`). 164 * 165 * @param {string} firstSnapshotFilePath 166 * The first snapshot file path. 167 * 168 * @param {string} secondSnapshotFilePath 169 * The second snapshot file path. 170 * 171 * @param {object} censusOptions 172 * A structured-cloneable object specifying the requested census's 173 * breakdown. See the "takeCensus" section of 174 * `js/src/doc/Debugger/Debugger.Memory.md` for detailed documentation. 175 * 176 * @param {object} requestOptions 177 * An object specifying options for this request. 178 * - {Boolean} asTreeNode 179 * Whether the resulting delta report should be converted to a census 180 * tree node before returned. Defaults to false. 181 * - {Boolean} asInvertedTreeNode 182 * Whether or not the census is returned as an inverted 183 * CensusTreeNode. Defaults to false. 184 * - {String} filter 185 * A filter string to prune the resulting tree with. Only applies if 186 * either asTreeNode or asInvertedTreeNode is true. 187 * 188 * @returns Promise<Object> 189 * - delta: 190 * The delta report generated by diffing the two census reports, or a 191 * CensusTreeNode generated from the delta report if 192 * `requestOptions.asTreeNode` was true. 193 * - parentMap: 194 * The result of calling CensusUtils.createParentMap on the generated 195 * delta. Only exists if asTreeNode or asInvertedTreeNode are set. 196 */ 197 HeapAnalysesClient.prototype.takeCensusDiff = function ( 198 firstSnapshotFilePath, 199 secondSnapshotFilePath, 200 censusOptions, 201 requestOptions = {} 202 ) { 203 return this._worker.performTask("takeCensusDiff", { 204 firstSnapshotFilePath, 205 secondSnapshotFilePath, 206 censusOptions, 207 requestOptions, 208 }); 209 }; 210 211 /*** Dominator Trees **********************************************************/ 212 213 /** 214 * Compute the dominator tree of the heap snapshot loaded from the given file 215 * path. Returns the id of the computed dominator tree. 216 * 217 * @param {string} snapshotFilePath 218 * 219 * @returns {Promise<DominatorTreeId>} 220 */ 221 HeapAnalysesClient.prototype.computeDominatorTree = function ( 222 snapshotFilePath 223 ) { 224 return this._worker.performTask("computeDominatorTree", snapshotFilePath); 225 }; 226 227 /** 228 * Get the initial, partial view of the dominator tree with the given id. 229 * 230 * @param {object} opts 231 * An object specifying options for this request. 232 * - {DominatorTreeId} dominatorTreeId 233 * The id of the dominator tree. 234 * - {Object} breakdown 235 * The breakdown used to generate node labels. 236 * - {Number} maxDepth 237 * The maximum depth to traverse down the tree to create this initial 238 * view. 239 * - {Number} maxSiblings 240 * The maximum number of siblings to visit within each traversed node's 241 * children. 242 * - {Number} maxRetainingPaths 243 * The maximum number of retaining paths to find for each node. 244 * 245 * @returns {Promise<DominatorTreeNode>} 246 */ 247 HeapAnalysesClient.prototype.getDominatorTree = function (opts) { 248 return this._worker.performTask("getDominatorTree", opts); 249 }; 250 251 /** 252 * Get a subset of a nodes children in the dominator tree. 253 * 254 * @param {object} opts 255 * An object specifying options for this request. 256 * - {DominatorTreeId} dominatorTreeId 257 * The id of the dominator tree. 258 * - {NodeId} nodeId 259 * The id of the node whose children are being found. 260 * - {Object} breakdown 261 * The breakdown used to generate node labels. 262 * - {Number} startIndex 263 * The starting index within the full set of immediately dominated 264 * children of the children being requested. Children are always sorted 265 * by greatest to least retained size. 266 * - {Number} maxCount 267 * The maximum number of children to return. 268 * - {Number} maxRetainingPaths 269 * The maximum number of retaining paths to find for each node. 270 * 271 * @returns {Promise<object>} 272 * A promise of an object with the following properties: 273 * - {Array<DominatorTreeNode>} nodes 274 * The requested nodes that are immediately dominated by the node 275 * identified by `opts.nodeId`. 276 * - {Boolean} moreChildrenAvailable 277 * True iff there are more children available after the returned 278 * nodes. 279 * - {Array<NodeId>} path 280 * The path through the tree from the root to these node's parent, eg 281 * [root's id, child of root's id, child of child of root's id, ..., `nodeId`]. 282 */ 283 HeapAnalysesClient.prototype.getImmediatelyDominated = function (opts) { 284 return this._worker.performTask("getImmediatelyDominated", opts); 285 };