From e9ee12c988d80f847f8163c0873db9639b3fa8f4 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Sun, 23 Feb 2020 10:38:36 -0500 Subject: Follow-up to 4e2e9be6a - Move HeapSnapshot DevTools-only Modules back to DevTools I am so done with this. Resolves #316 --- devtools/shared/heapsnapshot/HeapAnalysesClient.js | 277 +++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 devtools/shared/heapsnapshot/HeapAnalysesClient.js (limited to 'devtools/shared/heapsnapshot/HeapAnalysesClient.js') diff --git a/devtools/shared/heapsnapshot/HeapAnalysesClient.js b/devtools/shared/heapsnapshot/HeapAnalysesClient.js new file mode 100644 index 000000000..98601a2b1 --- /dev/null +++ b/devtools/shared/heapsnapshot/HeapAnalysesClient.js @@ -0,0 +1,277 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const DevToolsUtils = require("devtools/shared/DevToolsUtils"); +const { DevToolsWorker } = require("devtools/shared/worker/worker"); + +const WORKER_URL = + "resource://devtools/shared/heapsnapshot/HeapAnalysesWorker.js"; +var workerCounter = 0; + +/** + * A HeapAnalysesClient instance provides a developer-friendly interface for + * interacting with a HeapAnalysesWorker. This enables users to be ignorant of + * the message passing protocol used to communicate with the worker. The + * HeapAnalysesClient owns the worker, and terminating the worker is done by + * terminating the client (see the `destroy` method). + */ +const HeapAnalysesClient = module.exports = function () { + this._worker = new DevToolsWorker(WORKER_URL, { + name: `HeapAnalyses-${workerCounter++}`, + verbose: DevToolsUtils.dumpv.wantVerbose + }); +}; + +/** + * Destroy the worker, causing it to release its resources (such as heap + * snapshots it has deserialized and read into memory). The client is no longer + * usable after calling this method. + */ +HeapAnalysesClient.prototype.destroy = function () { + this._worker.destroy(); + this._worker = null; +}; + +/** + * Tell the worker to read into memory the heap snapshot at the given file + * path. This is a prerequisite for asking the worker to perform various + * analyses on a heap snapshot. + * + * @param {String} snapshotFilePath + * + * @returns Promise + * The promise is fulfilled if the heap snapshot is successfully + * deserialized and read into memory. The promise is rejected if that + * does not happen, eg due to a bad file path or malformed heap + * snapshot file. + */ +HeapAnalysesClient.prototype.readHeapSnapshot = function (snapshotFilePath) { + return this._worker.performTask("readHeapSnapshot", { snapshotFilePath }); +}; + +/** + * Tell the worker to delete all references to the snapshot and dominator trees + * linked to the provided snapshot file path. + * + * @param {String} snapshotFilePath + * @return Promise + */ +HeapAnalysesClient.prototype.deleteHeapSnapshot = function (snapshotFilePath) { + return this._worker.performTask("deleteHeapSnapshot", { snapshotFilePath }); +}; + +/** + * Request the creation time given a snapshot file path. Returns `null` + * if snapshot does not exist. + * + * @param {String} snapshotFilePath + * The path to the snapshot. + * @return {Number?} + * The unix timestamp of the creation time of the snapshot, or null if + * snapshot does not exist. + */ +HeapAnalysesClient.prototype.getCreationTime = function (snapshotFilePath) { + return this._worker.performTask("getCreationTime", snapshotFilePath); +}; + +/** * Censuses *****************************************************************/ + +/** + * Ask the worker to perform a census analysis on the heap snapshot with the + * given path. The heap snapshot at the given path must have already been read + * into memory by the worker (see `readHeapSnapshot`). + * + * @param {String} snapshotFilePath + * + * @param {Object} censusOptions + * A structured-cloneable object specifying the requested census's + * breakdown. See the "takeCensus" section of + * `js/src/doc/Debugger/Debugger.Memory.md` for detailed documentation. + * + * @param {Object} requestOptions + * An object specifying options of this worker request. + * - {Boolean} asTreeNode + * Whether or not the census is returned as a CensusTreeNode, + * or just a breakdown report. Defaults to false. + * @see `devtools/shared/heapsnapshot/census-tree-node.js` + * - {Boolean} asInvertedTreeNode + * Whether or not the census is returned as an inverted + * CensusTreeNode. Defaults to false. + * - {String} filter + * A filter string to prune the resulting tree with. Only applies if + * either asTreeNode or asInvertedTreeNode is true. + * + * @returns Promise + * An object with the following properties: + * - report: + * The report generated by the given census breakdown, or a + * CensusTreeNode generated by the given census breakdown if + * `asTreeNode` is true. + * - parentMap: + * The result of calling CensusUtils.createParentMap on the generated + * report. Only exists if asTreeNode or asInvertedTreeNode are set. + */ +HeapAnalysesClient.prototype.takeCensus = function (snapshotFilePath, + censusOptions, + requestOptions = {}) { + return this._worker.performTask("takeCensus", { + snapshotFilePath, + censusOptions, + requestOptions, + }); +}; + +/** + * Get the individual nodes that correspond to the given census report leaf + * indices. + * + * @param {Object} opts + * An object with the following properties: + * - {DominatorTreeId} dominatorTreeId: The id of the dominator tree. + * - {Set} indices: The indices of the census report leaves we + * would like to get the individuals for. + * - {Object} censusBreakdown: The breakdown used to generate the census. + * - {Object} labelBreakdown: The breakdown we would like to use when + * labeling the resulting nodes. + * - {Number} maxRetainingPaths: The maximum number of retaining paths to + * compute for each node. + * - {Number} maxIndividuals: The maximum number of individual nodes to + * return. + * + * @returns {Promise} + * A promise of an object with the following properties: + * - {Array} nodes: An array of `DominatorTreeNode`s + * with their shortest paths attached, and without any dominator tree + * child/parent information attached. The results are sorted by + * retained size. + * + */ +HeapAnalysesClient.prototype.getCensusIndividuals = function (opts) { + return this._worker.performTask("getCensusIndividuals", opts); +}; + +/** + * Request that the worker take a census on the heap snapshots with the given + * paths and then return the difference between them. Both heap snapshots must + * have already been read into memory by the worker (see `readHeapSnapshot`). + * + * @param {String} firstSnapshotFilePath + * The first snapshot file path. + * + * @param {String} secondSnapshotFilePath + * The second snapshot file path. + * + * @param {Object} censusOptions + * A structured-cloneable object specifying the requested census's + * breakdown. See the "takeCensus" section of + * `js/src/doc/Debugger/Debugger.Memory.md` for detailed documentation. + * + * @param {Object} requestOptions + * An object specifying options for this request. + * - {Boolean} asTreeNode + * Whether the resulting delta report should be converted to a census + * tree node before returned. Defaults to false. + * - {Boolean} asInvertedTreeNode + * Whether or not the census is returned as an inverted + * CensusTreeNode. Defaults to false. + * - {String} filter + * A filter string to prune the resulting tree with. Only applies if + * either asTreeNode or asInvertedTreeNode is true. + * + * @returns Promise + * - delta: + * The delta report generated by diffing the two census reports, or a + * CensusTreeNode generated from the delta report if + * `requestOptions.asTreeNode` was true. + * - parentMap: + * The result of calling CensusUtils.createParentMap on the generated + * delta. Only exists if asTreeNode or asInvertedTreeNode are set. + */ +HeapAnalysesClient.prototype.takeCensusDiff = function (firstSnapshotFilePath, + secondSnapshotFilePath, + censusOptions, + requestOptions = {}) { + return this._worker.performTask("takeCensusDiff", { + firstSnapshotFilePath, + secondSnapshotFilePath, + censusOptions, + requestOptions + }); +}; + +/** * Dominator Trees **********************************************************/ + +/** + * Compute the dominator tree of the heap snapshot loaded from the given file + * path. Returns the id of the computed dominator tree. + * + * @param {String} snapshotFilePath + * + * @returns {Promise} + */ +HeapAnalysesClient.prototype.computeDominatorTree = function (snapshotFilePath) { + return this._worker.performTask("computeDominatorTree", snapshotFilePath); +}; + +/** + * Get the initial, partial view of the dominator tree with the given id. + * + * @param {Object} opts + * An object specifying options for this request. + * - {DominatorTreeId} dominatorTreeId + * The id of the dominator tree. + * - {Object} breakdown + * The breakdown used to generate node labels. + * - {Number} maxDepth + * The maximum depth to traverse down the tree to create this initial + * view. + * - {Number} maxSiblings + * The maximum number of siblings to visit within each traversed node's + * children. + * - {Number} maxRetainingPaths + * The maximum number of retaining paths to find for each node. + * + * @returns {Promise} + */ +HeapAnalysesClient.prototype.getDominatorTree = function (opts) { + return this._worker.performTask("getDominatorTree", opts); +}; + +/** + * Get a subset of a nodes children in the dominator tree. + * + * @param {Object} opts + * An object specifying options for this request. + * - {DominatorTreeId} dominatorTreeId + * The id of the dominator tree. + * - {NodeId} nodeId + * The id of the node whose children are being found. + * - {Object} breakdown + * The breakdown used to generate node labels. + * - {Number} startIndex + * The starting index within the full set of immediately dominated + * children of the children being requested. Children are always sorted + * by greatest to least retained size. + * - {Number} maxCount + * The maximum number of children to return. + * - {Number} maxRetainingPaths + * The maximum number of retaining paths to find for each node. + * + * @returns {Promise} + * A promise of an object with the following properties: + * - {Array} nodes + * The requested nodes that are immediately dominated by the node + * identified by `opts.nodeId`. + * - {Boolean} moreChildrenAvailable + * True iff there are more children available after the returned + * nodes. + * - {Array} path + * The path through the tree from the root to these node's parent, eg + * [root's id, child of root's id, child of child of root's id, ..., `nodeId`]. + */ +HeapAnalysesClient.prototype.getImmediatelyDominated = function (opts) { + return this._worker.performTask("getImmediatelyDominated", opts); +}; -- cgit v1.2.3