/* 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";
/** * A single node in a dominator tree. * * @param {NodeId} nodeId * @param {NodeSize} retainedSize
*/ function DominatorTreeNode(nodeId, label, shallowSize, retainedSize) { // The id of this node. this.nodeId = nodeId;
// The label structure generated by describing the given node. this.label = label;
// The shallow size of this node. this.shallowSize = shallowSize;
// The retained size of this node. this.retainedSize = retainedSize;
// The id of this node's parent or undefined if this node is the root. this.parentId = undefined;
// An array of immediately dominated child `DominatorTreeNode`s, or undefined. this.children = undefined;
// An object of the form returned by `deduplicatePaths`, encoding the set of // the N shortest retaining paths for this node as a graph. this.shortestPaths = undefined;
// True iff the `children` property does not contain every immediately // dominated node. // // * If children is an array and this property is true: the array does not // contain the complete set of immediately dominated children. // * If children is an array and this property is false: the array contains // the complete set of immediately dominated children. // * If children is undefined and this property is true: there exist // immediately dominated children for this node, but they have not been // loaded yet. // * If children is undefined and this property is false: this node does not // dominate any others and therefore has no children. this.moreChildrenAvailable = true;
}
DominatorTreeNode.prototype = null;
module.exports = DominatorTreeNode;
/** * Add `child` to the `parent`'s set of children. * * @param {DominatorTreeNode} parent * @param {DominatorTreeNode} child
*/
DominatorTreeNode.addChild = function (parent, child) { if (parent.children === undefined) {
parent.children = [];
}
/** * A Visitor that is used to generate a label for a node in the heap snapshot * and get its shallow size as well while we are at it.
*/ function LabelAndShallowSizeVisitor() { // As we walk the description, we accumulate edges in this array. this._labelPieces = [];
// Once we reach the non-zero count leaf node in the description, we move the // labelPieces here to signify that we no longer need to accumulate edges. this._label = undefined;
// Once we reach the non-zero count leaf node in the description, we grab the // shallow size and place it here. this._shallowSize = 0;
}
/** * Get the generated label structure accumulated by this visitor. * * @returns {Object}
*/
LabelAndShallowSizeVisitor.prototype.label = function () { returnthis._label;
};
/** * Get the shallow size of the node this visitor visited. * * @returns {Number}
*/
LabelAndShallowSizeVisitor.prototype.shallowSize = function () { returnthis._shallowSize;
};
/** * Generate a label structure for the node with the given id and grab its * shallow size. * * What is a "label" structure? HeapSnapshot.describeNode essentially takes a * census of a single node rather than the whole heap graph. The resulting * report has only one count leaf that is non-zero. The label structure is the * path in this report from the root to the non-zero count leaf. * * @param {Number} nodeId * @param {HeapSnapshot} snapshot * @param {Object} breakdown * * @returns {Object} * An object with the following properties: * - {Number} shallowSize * - {Object} label
*/
DominatorTreeNode.getLabelAndShallowSize = function (
nodeId,
snapshot,
breakdown
) { const description = snapshot.describeNode(breakdown, nodeId);
const visitor = new LabelAndShallowSizeVisitor();
walk(breakdown, description, visitor);
/** * Do a partial traversal of the given dominator tree and convert it into a tree * of `DominatorTreeNode`s. Dominator trees have a node for every node in the * snapshot's heap graph, so we must not allocate a JS object for every node. It * would be way too many and the node count is effectively unbounded. * * Go no deeper down the tree than `maxDepth` and only consider at most * `maxSiblings` within any single node's children. * * @param {DominatorTree} dominatorTree * @param {HeapSnapshot} snapshot * @param {Object} breakdown * @param {Number} maxDepth * @param {Number} maxSiblings * * @returns {DominatorTreeNode}
*/
DominatorTreeNode.partialTraversal = function (
dominatorTree,
snapshot,
breakdown,
maxDepth = DEFAULT_MAX_DEPTH,
maxSiblings = DEFAULT_MAX_SIBLINGS
) { function dfs(nodeId, depth) { const { label, shallowSize } = DominatorTreeNode.getLabelAndShallowSize(
nodeId,
snapshot,
breakdown
); const retainedSize = dominatorTree.getRetainedSize(nodeId); const node = new DominatorTreeNode(
nodeId,
label,
shallowSize,
retainedSize
); const childNodeIds = dominatorTree.getImmediatelyDominated(nodeId);
/** * Insert more children into the given (partially complete) dominator tree. * * The tree is updated in an immutable and persistent manner: a new tree is * returned, but all unmodified subtrees (which is most) are shared with the * original tree. Only the modified nodes are re-allocated. * * @param {DominatorTreeNode} tree * @param {Array<NodeId>} path * @param {Array<DominatorTreeNode>} newChildren * @param {Boolean} moreChildrenAvailable * * @returns {DominatorTreeNode}
*/
DominatorTreeNode.insert = function (
nodeTree,
path,
newChildren,
moreChildrenAvailable
) { function insert(tree, i) { if (tree.nodeId !== path[i]) { return tree;
}
if (i == path.length - 1) { return immutableUpdate(tree, {
children: (tree.children || []).concat(newChildren),
moreChildrenAvailable,
});
}
/** * Get the new canonical node with the given `id` in `tree` that exists along * `path`. If there is no such node along `path`, return null. * * This is useful if we have a reference to a now-outdated DominatorTreeNode due * to a recent call to DominatorTreeNode.insert and want to get the up-to-date * version. We don't have to walk the whole tree: if there is an updated version * of the node then it *must* be along the path. * * @param {NodeId} id * @param {DominatorTreeNode} tree * @param {Array<NodeId>} path * * @returns {DominatorTreeNode|null}
*/
DominatorTreeNode.getNodeByIdAlongPath = function (id, tree, path) { function find(node, i) { if (!node || node.nodeId !== path[i]) { returnnull;
}
if (node.nodeId === id) { return node;
}
if (i === path.length - 1 || !node.children) { returnnull;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.27Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.