diff --git a/toolkit/components/aboutmemory/content/aboutMemory.css b/toolkit/components/aboutmemory/content/aboutMemory.css index 6ee14aa353cf..7b82e4b24f9b 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.css +++ b/toolkit/components/aboutmemory/content/aboutMemory.css @@ -35,10 +35,29 @@ * * ***** END LICENSE BLOCK ***** */ +body.verbose { + /* override setting in about.css */ + max-width: 100% !important; +} + +body.non-verbose pre.tree { + overflow-x: hidden; + text-overflow: ellipsis; +} + +.sectionHeader { + background: #ddd; + padding-left: .1em; +} + .accuracyWarning { color: #f00; } +.treeLine { + color: #888; +} + .mrValue { font-weight: bold; color: #400; @@ -47,20 +66,23 @@ .mrPerc { } -.mrName { - color: #004; +.mrSep { } -.hasDesc:hover { - text-decoration: underline; +.mrName { + color: #004; } .mrStar { color: #604; } -.treeLine { - color: #888; +.hasKids { + cursor: pointer; +} + +.hasKids:hover { + text-decoration: underline; } .option { @@ -73,22 +95,6 @@ -moz-user-select: none; /* no need to include this when cutting+pasting */ } -body.verbose { - /* override setting in about.css */ - max-width: 100% !important; -} - -h2.tree { - cursor: pointer; - background: #ddd; - padding-left: .1em; -} - -body.non-verbose pre.tree { - overflow-x: hidden; - text-overflow: ellipsis; -} - -pre.collapsed { +.hidden { display: none; } diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index 8aae22d1cbc1..776bf42155e6 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -199,17 +199,6 @@ function sendHeapMinNotifications() sendHeapMinNotificationsInner(); } -function toggleTreeVisibility(aEvent) -{ - var headerElem = aEvent.target; - - // Replace "header-" with "pre-" in the header element's id to get the id of - // the corresponding pre element. - var treeElem = $(headerElem.id.replace(/^header-/, 'pre-')); - - treeElem.classList.toggle('collapsed'); -} - function Reporter(aPath, aKind, aUnits, aAmount, aDescription) { this._path = aPath; @@ -337,6 +326,7 @@ function update() } // Memory-related actions. + const UpDesc = "Re-measure."; const GCDesc = "Do a global garbage collection."; const CCDesc = "Do a cycle collection."; const MPDesc = "Send three \"heap-minimize\" notifications in a " + @@ -345,7 +335,9 @@ function update() "process to reduce memory usage in other ways, e.g. by " + "flushing various caches."; + // The "Update" button has an id so it can be clicked in a test. text += "
" + + "" + "" + "" + "" + @@ -363,10 +355,12 @@ function update() "
"; text += "
" + - "Hover the pointer over the name of a memory " + - "reporter to see a detailed description of what it measures. Click a " + - "heading to expand or collapse its tree." + + "Click on a non-leaf node in a tree to expand ('++') " + + "or collapse ('--') its children." + "
"; + text += "
" + + "Hover the pointer over the name of a memory " + + "reporter to see a description of what it measures."; var div = document.createElement("div"); div.innerHTML = text; @@ -374,7 +368,7 @@ function update() } // There are two kinds of TreeNode. -// - Leaf TreeNodes correspond to Reporters and have more properties. +// - Leaf TreeNodes correspond to Reporters and have more properties. // - Non-leaf TreeNodes are just scaffolding nodes for the tree; their values // are derived from their children. function TreeNode(aName) @@ -390,6 +384,9 @@ function TreeNode(aName) // - _kind // - _nMerged (if > 1) // - _hasProblem (only defined if true) + // + // Non-leaf TreeNodes have these properties added later: + // - _hideKids (only defined if true) } TreeNode.prototype = { @@ -524,6 +521,25 @@ function buildTree(aReporters, aTreeName) return t; } +/** + * Ignore all the memory reporters that belong to a tree; this involves + * explicitly marking them as done. + * + * @param aReporters + * The table of Reporters, indexed by path. + * @param aTreeName + * The name of the tree being built. + */ +function ignoreTree(aReporters, aTreeName) +{ + for (var path in aReporters) { + var r = aReporters[path]; + if (r.treeNameMatches(aTreeName)) { + var dummy = getBytes(aReporters, path); + } + } +} + /** * Do some work which only makes sense for the 'explicit' tree. * @@ -581,58 +597,81 @@ function fixUpExplicitTree(aT, aReporters) } /** - * Sort all kid nodes from largest to smallest and aggregate insignificant - * nodes. + * Sort all kid nodes from largest to smallest, and insert aggregate nodes + * where appropriate. * * @param aTotalBytes * The size of the tree's root node. * @param aT * The tree. */ -function filterTree(aTotalBytes, aT) +function sortTreeAndInsertAggregateNodes(aTotalBytes, aT) { - const omitThresholdPerc = 0.5; /* percent */ + const kSignificanceThresholdPerc = 1; - function shouldOmit(aBytes) + function isInsignificant(aT) { return !gVerbose && aTotalBytes !== kUnknown && - (100 * aBytes / aTotalBytes) < omitThresholdPerc; + (100 * aT._amount / aTotalBytes) < kSignificanceThresholdPerc; + } + + if (aT._kids.length === 0) { + return; } aT._kids.sort(TreeNode.compare); - for (var i = 0; i < aT._kids.length; i++) { - if (shouldOmit(aT._kids[i]._amount)) { - // This sub-tree is below the significance threshold - // Remove it and all remaining (smaller) sub-trees, and - // replace them with a single aggregate node. + // If the first child is insignificant, they all are, and there's no point + // creating an aggregate node that lacks siblings. Just set the parent's + // _hideKids property and process all children. + if (isInsignificant(aT._kids[0])) { + aT._hideKids = true; + for (var i = 0; i < aT._kids.length; i++) { + sortTreeAndInsertAggregateNodes(aTotalBytes, aT._kids[i]); + } + return; + } + + // Look at all children except the last one. + for (var i = 0; i < aT._kids.length - 1; i++) { + if (isInsignificant(aT._kids[i])) { + // This child is below the significance threshold. If there are other + // (smaller) children remaining, move them under an aggregate node. var i0 = i; + var nAgg = aT._kids.length - i0; + // Create an aggregate node. + var aggT = new TreeNode("(" + nAgg + " tiny)"); var aggBytes = 0; for ( ; i < aT._kids.length; i++) { aggBytes += aT._kids[i]._amount; + aggT._kids.push(aT._kids[i]); } - aT._kids.splice(i0, aT._kids.length); - var n = i - i0; - var rSub = new TreeNode("(" + n + " omitted)"); - rSub._amount = aggBytes; - rSub._description = - n + " sub-trees that were below the " + omitThresholdPerc + - "% significance threshold. Click 'More verbose' at the bottom of " + - "this page to see them."; - - // Add the "omitted" sub-tree at the end and then re-sort, because the - // sum of the omitted sub-trees may be larger than some of the shown - // sub-trees. - aT._kids[i0] = rSub; + aggT._hideKids = true; + aggT._amount = aggBytes; + aggT._description = + nAgg + " sub-trees that are below the " + kSignificanceThresholdPerc + + "% significance threshold."; + aT._kids.splice(i0, nAgg, aggT); aT._kids.sort(TreeNode.compare); - break; + + // Process the moved children. + for (i = 0; i < aggT._kids.length; i++) { + sortTreeAndInsertAggregateNodes(aTotalBytes, aggT._kids[i]); + } + return; } - filterTree(aTotalBytes, aT._kids[i]); + + sortTreeAndInsertAggregateNodes(aTotalBytes, aT._kids[i]); } + + // The first n-1 children were significant. Don't consider if the last child + // is significant; there's no point creating an aggregate node that only has + // one child. Just process it. + sortTreeAndInsertAggregateNodes(aTotalBytes, aT._kids[i]); } -function genWarningText(aHasKnownHeapAllocated, aHasMozMallocUsableSize) +function genWarningText(aHasKnownHeapAllocated, aHasMozMallocUsableSize) { var warningText = ""; @@ -677,7 +716,7 @@ function genProcessText(aProcess, aReporters, aHasMozMallocUsableSize) { var explicitTree = buildTree(aReporters, 'explicit'); var hasKnownHeapAllocated = fixUpExplicitTree(explicitTree, aReporters); - filterTree(explicitTree._amount, explicitTree); + sortTreeAndInsertAggregateNodes(explicitTree._amount, explicitTree); var explicitText = genTreeText(explicitTree, aProcess); // Generate any warnings about inaccuracies due to platform limitations. @@ -687,14 +726,20 @@ function genProcessText(aProcess, aReporters, aHasMozMallocUsableSize) var warningText = genWarningText(hasKnownHeapAllocated, aHasMozMallocUsableSize); - var mapTreeText = ''; + // We only show these breakdown trees in verbose mode. + var mapTreeText = ""; kMapTreePaths.forEach(function(t) { - var tree = buildTree(aReporters, t); + if (gVerbose) { + var tree = buildTree(aReporters, t); - // |tree| will be null if we don't have any reporters for the given path. - if (tree) { - filterTree(tree._amount, tree); - mapTreeText += genTreeText(tree, aProcess); + // |tree| will be null if we don't have any reporters for the given path. + if (tree) { + sortTreeAndInsertAggregateNodes(tree._amount, tree); + tree._hideKids = true; // map trees are always initially collapsed + mapTreeText += genTreeText(tree, aProcess); + } + } else { + ignoreTree(aReporters, t); } }); @@ -835,9 +880,18 @@ function getDescription(aReporters, aPath) return r._description; } +// There's a subset of the Unicode "light" box-drawing chars that are widely +// implemented in terminals, and this code sticks to that subset to maximize +// the chance that cutting and pasting about:memory output to a terminal will +// work correctly: +const kHorizontal = "\u2500", + kVertical = "\u2502", + kUpAndRight = "\u2514", + kVerticalAndRight = "\u251c"; + function genMrValueText(aValue) { - return "" + aValue + ""; + return "" + aValue + " "; } function kindToString(aKind) @@ -861,7 +915,7 @@ function escapeAll(aStr) // Compartment reporter names are URLs and so can include forward slashes. But // forward slash is the memory reporter path separator. So the memory -// reporters change them to backslashes. Undo that here. +// reporters change them to backslashes. Undo that here. function flipBackslashes(aStr) { return aStr.replace(/\\/g, '/'); @@ -877,25 +931,86 @@ function prepDesc(aStr) return escapeAll(flipBackslashes(aStr)); } -function genMrNameText(aKind, aDesc, aName, aHasProblem, aNMerged) +function genMrNameText(aKind, aShowSubtrees, aHasKids, aDesc, aName, + aHasProblem, aNMerged) { - var text = "-- " + prepName(aName) + ""; + var text = ""; + if (aHasKids) { + if (aShowSubtrees) { + text += ""; + text += "-- "; + } else { + text += "++ "; + text += ""; + } + } else { + text += "" + kHorizontal + kHorizontal + " "; + } + text += "" + + prepName(aName) + ""; if (aHasProblem) { const problemDesc = "Warning: this memory reporter was unable to compute a useful value. "; - text += " [*]"; + text += " [*]"; } if (aNMerged) { const dupDesc = "This value is the sum of " + aNMerged + " memory reporters that all have the same path."; - text += " [" + + text += " [" + aNMerged + "]"; } return text + '\n'; } +// This is used to record which sub-trees have been toggled, so the +// collapsed/expanded state can be replicated when the page is regenerated. +// It can end up holding IDs of nodes that no longer exist, e.g. for +// compartments that have been closed. This doesn't seem like a big deal, +// because the number is limited by the number of entries the user has changed +// from their original state. +var gToggles = {}; + +function toggle(aEvent) +{ + // This relies on each line being a span that contains at least five spans: + // mrValue, mrPerc, mrSep ('++'), mrSep ('--'), mrName, and then zero or more + // mrStars. All whitespace must be within one of these spans for this + // function to find the right nodes. And the span containing the children of + // this line must immediately follow. Assertions check this. + + function assertClassName(span, className) { + assert(span, "undefined " + className); + assert(span.nodeName === "span", "non-span " + className); + assert(span.classList.contains(className), "bad " + className); + } + + // |aEvent.target| will be one of the five spans. Get the outer span. + var outerSpan = aEvent.target.parentNode; + assertClassName(outerSpan, "hasKids"); + + // Toggle visibility of the '++' and '--' separators. + var plusSpan = outerSpan.childNodes[2]; + var minusSpan = outerSpan.childNodes[3]; + assertClassName(plusSpan, "mrSep"); + assertClassName(minusSpan, "mrSep"); + plusSpan .classList.toggle("hidden"); + minusSpan.classList.toggle("hidden"); + + // Toggle visibility of the span containing this node's children. + var subTreeSpan = outerSpan.nextSibling; + assertClassName(subTreeSpan, "kids"); + subTreeSpan.classList.toggle("hidden"); + + // Record/unrecord that this sub-tree was toggled. + var treeId = outerSpan.id; + if (gToggles[treeId]) { + delete gToggles[treeId]; + } else { + gToggles[treeId] = true; + } +} + /** * Generates the text for the tree, including its heading. * @@ -914,6 +1029,8 @@ function genTreeText(aT, aProcess) /** * Generates the text for a particular tree, without a heading. * + * @param aPrePath + * The partial path leading up to this node. * @param aT * The tree. * @param aIndentGuide @@ -925,7 +1042,7 @@ function genTreeText(aT, aProcess) * The length of the formatted byte count of the top node in the tree. * @return The generated text. */ - function genTreeText2(aT, aIndentGuide, aParentStringLength) + function genTreeText2(aPrePath, aT, aIndentGuide, aParentStringLength) { function repeatStr(aC, aN) { @@ -936,15 +1053,7 @@ function genTreeText(aT, aProcess) return s; } - // Generate the indent. There's a subset of the Unicode "light" - // box-drawing chars that are widely implemented in terminals, and - // this code sticks to that subset to maximize the chance that - // cutting and pasting about:memory output to a terminal will work - // correctly: - const kHorizontal = "\u2500", - kVertical = "\u2502", - kUpAndRight = "\u2514", - kVerticalAndRight = "\u251c"; + // Generate the indent. var indent = ""; if (aIndentGuide.length > 0) { for (var i = 0; i < aIndentGuide.length - 1; i++) { @@ -954,7 +1063,6 @@ function genTreeText(aT, aProcess) indent += aIndentGuide[i]._isLastKid ? kUpAndRight : kVerticalAndRight; indent += repeatStr(kHorizontal, aIndentGuide[i]._depth - 1); } - // Indent more if this entry is narrower than its parent, and update // aIndentGuide accordingly. var tString = aT.toString(); @@ -967,40 +1075,66 @@ function genTreeText(aT, aProcess) } indent += ""; - // Generate the percentage. - var perc = ""; + // Generate the percentage, and determine if we should show subtrees. + var percText = ""; + var showSubtrees = !aT._hideKids; if (aT._amount === treeBytes) { - perc = "100.0"; + percText = "100.0"; } else { - perc = (100 * aT._amount / treeBytes).toFixed(2); - perc = pad(perc, 5, '0'); + var perc = (100 * aT._amount / treeBytes); + percText = (100 * aT._amount / treeBytes).toFixed(2); + percText = pad(percText, 5, '0'); + } + percText = "(" + percText + "%) "; + + // Reinstate any previous toggling of this sub-tree. + var path = aPrePath + aT._name; + var treeId = escapeAll(aProcess + ":" + path); + if (gToggles[treeId]) { + showSubtrees = !showSubtrees; } - perc = "(" + perc + "%) "; // We don't want to show '(nonheap)' on a tree like 'map/vsize', since the // whole tree is non-heap. var kind = isExplicitTree ? aT._kind : undefined; - var text = indent + genMrValueText(tString) + " " + perc + - genMrNameText(kind, aT._description, aT._name, - aT._hasProblem, aT._nMerged); + + // For non-leaf nodes, the entire sub-tree is put within a span so it can + // be collapsed if the node is clicked on. + var hasKids = aT._kids.length > 0; + if (!hasKids) { + assert(!aT._hideKids, "leaf node with _hideKids set") + } + var text = indent; + if (hasKids) { + text += + ""; + } + text += genMrValueText(tString) + percText; + text += genMrNameText(kind, showSubtrees, hasKids, aT._description, + aT._name, aT._hasProblem, aT._nMerged); + if (hasKids) { + var hiddenText = showSubtrees ? "" : " hidden"; + // The 'kids' class is just used for sanity checking in toggle(). + text += ""; + } for (var i = 0; i < aT._kids.length; i++) { // 3 is the standard depth, the callee adjusts it if necessary. aIndentGuide.push({ _isLastKid: (i === aT._kids.length - 1), _depth: 3 }); - text += genTreeText2(aT._kids[i], aIndentGuide, tString.length); + text += genTreeText2(path + "/", aT._kids[i], aIndentGuide, + tString.length); aIndentGuide.pop(); } + text += hasKids ? "" : ""; return text; } - var text = genTreeText2(aT, [], rootStringLength); + var text = genTreeText2(/* prePath = */"", aT, [], rootStringLength); - // The explicit tree is not collapsed, but all other trees are, so pass - // !isExplicitTree for genSectionMarkup's aCollapsed parameter. - return genSectionMarkup(aProcess, aT._name, text, !isExplicitTree); + return genSectionMarkup(aT._name, text); } -function OtherReporter(aPath, aUnits, aAmount, aDescription, +function OtherReporter(aPath, aUnits, aAmount, aDescription, aNMerged) { // Nb: _kind is not needed, it's always KIND_OTHER. @@ -1055,7 +1189,7 @@ function genOtherText(aReportersByProcess, aProcess) var r = aReportersByProcess[path]; if (!r._done) { assert(r._kind === KIND_OTHER, "_kind !== KIND_OTHER for " + r._path); - assert(r.nMerged === undefined); // we don't allow dup'd OTHER reporters + assert(r.nMerged === undefined); // we don't allow dup'd OTHER reporters var hasProblem = false; if (r._amount === kUnknown) { hasProblem = true; @@ -1073,29 +1207,19 @@ function genOtherText(aReportersByProcess, aProcess) var text = ""; for (var i = 0; i < otherReporters.length; i++) { var o = otherReporters[i]; - text += genMrValueText(pad(o.asString, maxStringLength, ' ')) + " "; - text += genMrNameText(KIND_OTHER, o._description, o._path, o._hasProblem); + text += genMrValueText(pad(o.asString, maxStringLength, ' ')); + text += genMrNameText(KIND_OTHER, /* showSubtrees = */true, + /* hasKids = */false, o._description, o._path, + o._hasProblem); } - // Nb: the newlines give nice spacing if we cut+paste into a text buffer. - const desc = "This list contains other memory measurements that cross-cut " + - "the requested memory measurements above." - - return genSectionMarkup(aProcess, 'other', text, false); + return genSectionMarkup('other', text); } -function genSectionMarkup(aProcess, aName, aText, aCollapsed) +function genSectionMarkup(aName, aText) { - var headerId = 'header-' + aProcess + '-' + aName; - var preId = 'pre-' + aProcess + '-' + aName; - var elemClass = (aCollapsed ? 'collapsed' : '') + ' tree'; - - // Ugh. - return '

' + - kTreeNames[aName] + - '

\n' + - '
' + aText + '
\n'; + return "

" + kTreeNames[aName] + "

\n" + + "
" + aText + "
\n"; } function assert(aCond, aMsg) diff --git a/toolkit/components/aboutmemory/tests/Makefile.in b/toolkit/components/aboutmemory/tests/Makefile.in index 802b23877766..bffd47a7e87d 100644 --- a/toolkit/components/aboutmemory/tests/Makefile.in +++ b/toolkit/components/aboutmemory/tests/Makefile.in @@ -46,6 +46,7 @@ include $(topsrcdir)/config/rules.mk _CHROME_FILES = \ test_aboutmemory.xul \ + test_aboutmemory2.xul \ test_sqliteMultiReporter.xul \ $(NULL) diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul index f52751ef23b0..1289509853d3 100644 --- a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul @@ -123,6 +123,7 @@ f("map/vsize/a", 19); f("map/swap/b/c", 10); f("map/resident/a", 42); + f("map/pss/a", 43); }, explicitNonHeap: 0 } @@ -186,50 +187,33 @@ Main Process\n\ Explicit Allocations\n\ 623.58 MB (100.0%) -- explicit\n\ ├──232.00 MB (37.20%) -- b\n\ -│ ├───85.00 MB (13.63%) -- a\n\ -│ ├───75.00 MB (12.03%) -- b\n\ +│ ├───85.00 MB (13.63%) ── a\n\ +│ ├───75.00 MB (12.03%) ── b\n\ │ └───72.00 MB (11.55%) -- c\n\ -│ ├──70.00 MB (11.23%) -- a\n\ -│ └───2.00 MB (00.32%) -- (1 omitted)\n\ -├──222.00 MB (35.60%) -- a\n\ +│ ├──70.00 MB (11.23%) ── a\n\ +│ └───2.00 MB (00.32%) ── b\n\ +├──222.00 MB (35.60%) ── a\n\ ├──100.00 MB (16.04%) -- c\n\ -│ ├───77.00 MB (12.35%) -- other\n\ -│ └───23.00 MB (03.69%) -- d [2]\n\ -├───23.00 MB (03.69%) -- cc [2]\n\ +│ ├───77.00 MB (12.35%) ── other\n\ +│ └───23.00 MB (03.69%) ── d [2]\n\ +├───23.00 MB (03.69%) ── cc [2]\n\ ├───20.00 MB (03.21%) -- f\n\ │ └──20.00 MB (03.21%) -- g\n\ │ └──20.00 MB (03.21%) -- h\n\ -│ └──20.00 MB (03.21%) -- i\n\ -├───15.00 MB (02.41%) -- g\n\ -│ ├───6.00 MB (00.96%) -- a\n\ -│ ├───5.00 MB (00.80%) -- b\n\ -│ └───4.00 MB (00.64%) -- other\n\ -├───11.00 MB (01.76%) -- heap-unclassified\n\ -└────0.58 MB (00.09%) -- (2 omitted)\n\ -\n\ -Resident Set Size (RSS) Breakdown\n\ -0.16 MB (100.0%) -- resident\n\ -└──0.16 MB (100.0%) -- a\n\ -\n\ -Virtual Size Breakdown\n\ -0.17 MB (100.0%) -- vsize\n\ -└──0.17 MB (100.0%) -- a [2]\n\ -\n\ -Swap Usage Breakdown\n\ -0.05 MB (100.0%) -- swap\n\ -├──0.04 MB (76.92%) -- b\n\ -│ └──0.04 MB (76.92%) -- c\n\ -└──0.01 MB (23.08%) -- a [2]\n\ +│ └──20.00 MB (03.21%) ── i\n\ +├───15.00 MB (02.41%) ++ g\n\ +├───11.00 MB (01.76%) ── heap-unclassified\n\ +└────0.58 MB (00.09%) ++ (2 tiny)\n\ \n\ Other Measurements\n\ -500.00 MB -- heap-allocated\n\ -100.00 MB -- heap-unallocated\n\ -111.00 MB -- other1\n\ -222.00 MB -- other2\n\ - 777 -- other3\n\ - 888 -- other4\n\ - 45.67% -- perc1\n\ - 100.00% -- perc2\n\ +500.00 MB ── heap-allocated\n\ +100.00 MB ── heap-unallocated\n\ +111.00 MB ── other1\n\ +222.00 MB ── other2\n\ + 777 ── other3\n\ + 888 ── other4\n\ + 45.67% ── perc1\n\ + 100.00% ── perc2\n\ \n\ 2nd Process\n\ \n\ @@ -237,16 +221,16 @@ Explicit Allocations\n\ 1,000.00 MB (100.0%) -- explicit\n\ ├────499.00 MB (49.90%) -- a\n\ │ └──499.00 MB (49.90%) -- b\n\ -│ └──499.00 MB (49.90%) -- c [3]\n\ -├────200.00 MB (20.00%) -- flip/the/backslashes\n\ -├────200.00 MB (20.00%) -- compartment(compartment-url)\n\ -└────101.00 MB (10.10%) -- heap-unclassified\n\ +│ └──499.00 MB (49.90%) ── c [3]\n\ +├────200.00 MB (20.00%) ── flip/the/backslashes\n\ +├────200.00 MB (20.00%) ── compartment(compartment-url)\n\ +└────101.00 MB (10.10%) ── heap-unclassified\n\ \n\ Other Measurements\n\ - 666.00 MB -- danger\n\ -1,000.00 MB -- heap-allocated\n\ - 100.00 MB -- heap-unallocated\n\ - 111.00 MB -- other1\n\ + 666.00 MB ── danger\n\ +1,000.00 MB ── heap-allocated\n\ + 100.00 MB ── heap-unallocated\n\ + 111.00 MB ── other1\n\ \n\ 3rd Process\n\ \n\ @@ -255,14 +239,14 @@ WARNING: the 'heap-allocated' memory reporter does not work for this platform an Explicit Allocations\n\ 777.00 MB (100.0%) -- explicit\n\ ├──777.00 MB (100.0%) -- a\n\ -│ ├──444.00 MB (57.14%) -- c [2]\n\ -│ ├──333.00 MB (42.86%) -- b\n\ -│ └────0.00 MB (00.00%) -- (1 omitted)\n\ -└────0.00 MB (00.00%) -- (2 omitted)\n\ +│ ├──444.00 MB (57.14%) ── c [2]\n\ +│ ├──333.00 MB (42.86%) ── b\n\ +│ └────0.00 MB (00.00%) ── d [*] [2]\n\ +└────0.00 MB (00.00%) ++ (2 tiny)\n\ \n\ Other Measurements\n\ -0.00 MB -- heap-allocated [*]\n\ -0.00 MB -- other1 [*]\n\ +0.00 MB ── heap-allocated [*]\n\ +0.00 MB ── other1 [*]\n\ \n\ "; @@ -273,51 +257,49 @@ Main Process\n\ Explicit Allocations\n\ 653,876,224 B (100.0%) -- explicit\n\ ├──243,269,632 B (37.20%) -- b\n\ -│ ├───89,128,960 B (13.63%) -- a\n\ -│ ├───78,643,200 B (12.03%) -- b\n\ +│ ├───89,128,960 B (13.63%) ── a\n\ +│ ├───78,643,200 B (12.03%) ── b\n\ │ └───75,497,472 B (11.55%) -- c\n\ -│ ├──73,400,320 B (11.23%) -- a\n\ -│ └───2,097,152 B (00.32%) -- b\n\ -├──232,783,872 B (35.60%) -- a\n\ +│ ├──73,400,320 B (11.23%) ── a\n\ +│ └───2,097,152 B (00.32%) ── b\n\ +├──232,783,872 B (35.60%) ── a\n\ ├──104,857,600 B (16.04%) -- c\n\ -│ ├───80,740,352 B (12.35%) -- other\n\ -│ └───24,117,248 B (03.69%) -- d [2]\n\ -├───24,117,248 B (03.69%) -- cc [2]\n\ +│ ├───80,740,352 B (12.35%) ── other\n\ +│ └───24,117,248 B (03.69%) ── d [2]\n\ +├───24,117,248 B (03.69%) ── cc [2]\n\ ├───20,971,520 B (03.21%) -- f\n\ │ └──20,971,520 B (03.21%) -- g\n\ │ └──20,971,520 B (03.21%) -- h\n\ -│ └──20,971,520 B (03.21%) -- i\n\ +│ └──20,971,520 B (03.21%) ── i\n\ ├───15,728,640 B (02.41%) -- g\n\ -│ ├───6,291,456 B (00.96%) -- a\n\ -│ ├───5,242,880 B (00.80%) -- b\n\ -│ └───4,194,304 B (00.64%) -- other\n\ -├───11,534,336 B (01.76%) -- heap-unclassified\n\ -├──────510,976 B (00.08%) -- d\n\ -└──────102,400 B (00.02%) -- e\n\ +│ ├───6,291,456 B (00.96%) ── a\n\ +│ ├───5,242,880 B (00.80%) ── b\n\ +│ └───4,194,304 B (00.64%) ── other\n\ +├───11,534,336 B (01.76%) ── heap-unclassified\n\ +├──────510,976 B (00.08%) ── d\n\ +└──────102,400 B (00.02%) ── e\n\ \n\ Resident Set Size (RSS) Breakdown\n\ -172,032 B (100.0%) -- resident\n\ -└──172,032 B (100.0%) -- a\n\ +172,032 B (100.0%) ++ resident\n\ +\n\ +Proportional Set Size (PSS) Breakdown\n\ +176,128 B (100.0%) ++ pss\n\ \n\ Virtual Size Breakdown\n\ -176,128 B (100.0%) -- vsize\n\ -└──176,128 B (100.0%) -- a [2]\n\ +176,128 B (100.0%) ++ vsize\n\ \n\ Swap Usage Breakdown\n\ -53,248 B (100.0%) -- swap\n\ -├──40,960 B (76.92%) -- b\n\ -│ └──40,960 B (76.92%) -- c\n\ -└──12,288 B (23.08%) -- a [2]\n\ +53,248 B (100.0%) ++ swap\n\ \n\ Other Measurements\n\ -524,288,000 B -- heap-allocated\n\ -104,857,600 B -- heap-unallocated\n\ -116,391,936 B -- other1\n\ -232,783,872 B -- other2\n\ - 777 -- other3\n\ - 888 -- other4\n\ - 45.67% -- perc1\n\ - 100.00% -- perc2\n\ +524,288,000 B ── heap-allocated\n\ +104,857,600 B ── heap-unallocated\n\ +116,391,936 B ── other1\n\ +232,783,872 B ── other2\n\ + 777 ── other3\n\ + 888 ── other4\n\ + 45.67% ── perc1\n\ + 100.00% ── perc2\n\ \n\ 2nd Process\n\ \n\ @@ -325,16 +307,16 @@ Explicit Allocations\n\ 1,048,576,000 B (100.0%) -- explicit\n\ ├────523,239,424 B (49.90%) -- a\n\ │ └──523,239,424 B (49.90%) -- b\n\ -│ └──523,239,424 B (49.90%) -- c [3]\n\ -├────209,715,200 B (20.00%) -- flip/the/backslashes\n\ -├────209,715,200 B (20.00%) -- compartment(compartment-url)\n\ -└────105,906,176 B (10.10%) -- heap-unclassified\n\ +│ └──523,239,424 B (49.90%) ── c [3]\n\ +├────209,715,200 B (20.00%) ── flip/the/backslashes\n\ +├────209,715,200 B (20.00%) ── compartment(compartment-url)\n\ +└────105,906,176 B (10.10%) ── heap-unclassified\n\ \n\ Other Measurements\n\ - 698,351,616 B -- danger\n\ -1,048,576,000 B -- heap-allocated\n\ - 104,857,600 B -- heap-unallocated\n\ - 116,391,936 B -- other1\n\ + 698,351,616 B ── danger\n\ +1,048,576,000 B ── heap-allocated\n\ + 104,857,600 B ── heap-unallocated\n\ + 116,391,936 B ── other1\n\ \n\ 3rd Process\n\ \n\ @@ -343,15 +325,15 @@ WARNING: the 'heap-allocated' memory reporter does not work for this platform an Explicit Allocations\n\ 814,743,552 B (100.0%) -- explicit\n\ ├──814,743,552 B (100.0%) -- a\n\ -│ ├──465,567,744 B (57.14%) -- c [2]\n\ -│ ├──349,175,808 B (42.86%) -- b\n\ -│ └────────────0 B (00.00%) -- d [*] [2]\n\ -├────────────0 B (00.00%) -- b [*]\n\ -└────────────0 B (00.00%) -- heap-unclassified [*]\n\ +│ ├──465,567,744 B (57.14%) ── c [2]\n\ +│ ├──349,175,808 B (42.86%) ── b\n\ +│ └────────────0 B (00.00%) ── d [*] [2]\n\ +├────────────0 B (00.00%) ── b [*]\n\ +└────────────0 B (00.00%) ── heap-unclassified [*]\n\ \n\ Other Measurements\n\ -0 B -- heap-allocated [*]\n\ -0 B -- other1 [*]\n\ +0 B ── heap-allocated [*]\n\ +0 B ── other1 [*]\n\ \n\ " @@ -375,13 +357,18 @@ Other Measurements\n\ SimpleTest.finish(); } + var gHaveDumped = false; + function checkClipboard(actual, expected) { if (actual != expected) { - dump("*******ACTUAL*******\n"); - dump(actual); - dump("******EXPECTED******\n"); - dump(expected); - dump("********************\n"); + if (!gHaveDumped) { + dump("******EXPECTED******\n"); + dump(expected); + dump("*******ACTUAL*******\n"); + dump(actual); + dump("********************\n"); + gHaveDumped = true; + } return false; } return true; @@ -391,15 +378,8 @@ Other Measurements\n\ // expect. This tests the output in general and also that the cutting and // pasting works as expected. function test(aFrame, aExpectedText, aNext) { - // Click all h2.collapsed elements so they expand. - var win = document.querySelector("#" + aFrame).contentWindow; - var nodes = win.document.querySelectorAll("pre.collapsed"); - for (var i = 0; i < nodes.length; i++) { - nodes[i].classList.toggle('collapsed'); - } - SimpleTest.executeSoon(function() { - document.querySelector("#" + aFrame).focus(); + document.getElementById(aFrame).focus(); SimpleTest.waitForClipboard( function(actual) { return checkClipboard(actual, aExpectedText) }, function() { diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul new file mode 100644 index 000000000000..d8bc318d4597 --- /dev/null +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory2.xul @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + +