mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 669611 - Add memory reporter for GC heap fragmentation. r=jlebar.
This commit is contained in:
parent
b4cb3cd58d
commit
29686fd711
@ -23,6 +23,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* John Bandhauer <jband@netscape.com> (original author)
|
||||
* Nicholas Nethercote <nnethercote@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -1552,14 +1553,19 @@ public:
|
||||
NS_NAMED_LITERAL_CSTRING(p, "");
|
||||
|
||||
PRInt64 gcHeapChunkTotal = gXPCJSChunkAllocator.GetGCChunkBytesInUse();
|
||||
// This is initialized to gcHeapChunkUnused, and then we subtract used
|
||||
// This is initialized to gcHeapChunkTotal, and then we subtract used
|
||||
// space from it each time around the loop.
|
||||
PRInt64 gcHeapChunkUnused = gcHeapChunkTotal;
|
||||
PRInt64 gcHeapArenaUnused = 0;
|
||||
|
||||
#define DO(path, kind, amount, desc) \
|
||||
#define BYTES(path, kind, amount, desc) \
|
||||
callback->Callback(p, path, kind, nsIMemoryReporter::UNITS_BYTES, \
|
||||
amount, NS_LITERAL_CSTRING(desc), closure);
|
||||
|
||||
#define PERCENTAGE(path, kind, amount, desc) \
|
||||
callback->Callback(p, path, kind, nsIMemoryReporter::UNITS_PERCENTAGE, \
|
||||
amount, NS_LITERAL_CSTRING(desc), closure);
|
||||
|
||||
// This is the second step (see above).
|
||||
for (CompartmentStats *stats = data.compartmentStatsVector.begin();
|
||||
stats != data.compartmentStatsVector.end();
|
||||
@ -1573,85 +1579,95 @@ public:
|
||||
stats->gcHeapObjects + stats->gcHeapStrings +
|
||||
stats->gcHeapShapes + stats->gcHeapXml;
|
||||
|
||||
DO(mkPath(name, "gc-heap/arena-headers"),
|
||||
gcHeapArenaUnused += stats->gcHeapArenaUnused;
|
||||
|
||||
BYTES(mkPath(name, "gc-heap/arena-headers"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapArenaHeaders,
|
||||
"Memory on the garbage-collected JavaScript heap, within arenas, that is "
|
||||
"used to hold internal book-keeping information.");
|
||||
"Memory on the compartment's garbage-collected JavaScript heap, within "
|
||||
"arenas, that is used to hold internal book-keeping information.");
|
||||
|
||||
DO(mkPath(name, "gc-heap/arena-padding"),
|
||||
BYTES(mkPath(name, "gc-heap/arena-padding"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapArenaPadding,
|
||||
"Memory on the garbage-collected JavaScript heap, within arenas, that is "
|
||||
"unused and present only so that other data is aligned.");
|
||||
"Memory on the compartment's garbage-collected JavaScript heap, within "
|
||||
"arenas, that is unused and present only so that other data is aligned. "
|
||||
"This constitutes internal fragmentation.");
|
||||
|
||||
DO(mkPath(name, "gc-heap/arena-unused"),
|
||||
BYTES(mkPath(name, "gc-heap/arena-unused"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapArenaUnused,
|
||||
"Memory on the garbage-collected JavaScript heap, within arenas, that "
|
||||
"could be holding useful data but currently isn't.");
|
||||
"Memory on the compartment's garbage-collected JavaScript heap, within "
|
||||
"arenas, that could be holding useful data but currently isn't.");
|
||||
|
||||
DO(mkPath(name, "gc-heap/objects"),
|
||||
BYTES(mkPath(name, "gc-heap/objects"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapObjects,
|
||||
"Memory on the garbage-collected JavaScript heap that holds objects.");
|
||||
|
||||
DO(mkPath(name, "gc-heap/strings"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapStrings,
|
||||
"Memory on the garbage-collected JavaScript heap that holds string "
|
||||
"headers.");
|
||||
|
||||
DO(mkPath(name, "gc-heap/shapes"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapShapes,
|
||||
"Memory on the garbage-collected JavaScript heap that holds shapes. "
|
||||
"A shape is an internal data structure that makes property accesses "
|
||||
"fast.");
|
||||
|
||||
DO(mkPath(name, "gc-heap/xml"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapXml,
|
||||
"Memory on the garbage-collected JavaScript heap that holds E4X XML "
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"objects.");
|
||||
|
||||
DO(mkPath(name, "object-slots"),
|
||||
BYTES(mkPath(name, "gc-heap/strings"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapStrings,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"string headers. String headers contain various pieces of information "
|
||||
"about a string, but do not contain (except in the case of very short "
|
||||
"strings) the string characters; characters in longer strings are counted "
|
||||
"under 'gc-heap/string-chars' instead.");
|
||||
|
||||
BYTES(mkPath(name, "gc-heap/shapes"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapShapes,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"shapes. A shape is an internal data structure that makes JavaScript "
|
||||
"property accesses fast.");
|
||||
|
||||
BYTES(mkPath(name, "gc-heap/xml"),
|
||||
JS_GC_HEAP_KIND, stats->gcHeapXml,
|
||||
"Memory on the compartment's garbage-collected JavaScript heap that holds "
|
||||
"E4X XML objects.");
|
||||
|
||||
BYTES(mkPath(name, "object-slots"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats->objectSlots,
|
||||
"Memory allocated for non-fixed object slot arrays, which are used "
|
||||
"to represent object properties. Some objects also contain a fixed "
|
||||
"number of slots which are stored on the JavaScript heap; those slots "
|
||||
"are not counted here, but in 'gc-heap/objects'.");
|
||||
"Memory allocated for the compartment's non-fixed object slot arrays, "
|
||||
"which are used to represent object properties. Some objects also "
|
||||
"contain a fixed number of slots which are stored on the compartment's "
|
||||
"JavaScript heap; those slots are not counted here, but in "
|
||||
"'gc-heap/objects' instead.");
|
||||
|
||||
DO(mkPath(name, "string-chars"),
|
||||
BYTES(mkPath(name, "string-chars"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats->stringChars,
|
||||
"Memory allocated to hold string characters. Not all of this allocated "
|
||||
"memory is necessarily used to hold characters. Each string also "
|
||||
"includes a header which is stored on the JavaScript heap; that header "
|
||||
"is not counted here, but in 'gc-heap/strings'.");
|
||||
"Memory allocated to hold the compartment's string characters. Sometimes "
|
||||
"more memory is allocated than necessary, to simplify string "
|
||||
"concatenation. Each string also includes a header which is stored on the "
|
||||
"compartment's JavaScript heap; that header is not counted here, but in "
|
||||
"'gc-heap/strings' instead.");
|
||||
|
||||
DO(mkPath(name, "scripts"),
|
||||
BYTES(mkPath(name, "scripts"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats->scripts,
|
||||
"Memory allocated for JSScripts. A JSScript is created for each "
|
||||
"user-defined function in a script. One is also created for "
|
||||
"Memory allocated for the compartment's JSScripts. A JSScript is created "
|
||||
"for each user-defined function in a script. One is also created for "
|
||||
"the top-level code in a script. Each JSScript includes byte-code and "
|
||||
"various other things.");
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
DO(mkPath(name, "mjit-code"),
|
||||
BYTES(mkPath(name, "mjit-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, stats->mjitCode,
|
||||
"Memory used by the method JIT to hold generated code.");
|
||||
"Memory used by the method JIT to hold the compartment's generated code.");
|
||||
|
||||
DO(mkPath(name, "mjit-data"),
|
||||
BYTES(mkPath(name, "mjit-data"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats->mjitData,
|
||||
"Memory used by the method JIT for the following data: "
|
||||
"Memory used by the method JIT for the compartment's compilation data: "
|
||||
"JITScripts, native maps, and inline cache structs.");
|
||||
#endif
|
||||
#ifdef JS_TRACER
|
||||
DO(mkPath(name, "tjit-code"),
|
||||
BYTES(mkPath(name, "tjit-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, stats->tjitCode,
|
||||
"Memory used by the trace JIT to hold generated code.");
|
||||
"Memory used by the trace JIT to hold the compartment's generated code.");
|
||||
|
||||
DO(mkPath(name, "tjit-data/allocators-main"),
|
||||
BYTES(mkPath(name, "tjit-data/allocators-main"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats->tjitDataAllocatorsMain,
|
||||
"Memory used by the trace JIT's VMAllocators.");
|
||||
"Memory used by the trace JIT to store the compartment's trace-related "
|
||||
"data. This data is allocated via the compartment's VMAllocators.");
|
||||
|
||||
DO(mkPath(name, "tjit-data/allocators-reserve"),
|
||||
BYTES(mkPath(name, "tjit-data/allocators-reserve"),
|
||||
nsIMemoryReporter::KIND_HEAP, stats->tjitDataAllocatorsReserve,
|
||||
"Memory used by the trace JIT and held in reserve for VMAllocators "
|
||||
"in case of OOM.");
|
||||
"Memory used by the trace JIT and held in reserve for the compartment's "
|
||||
"VMAllocators in case of OOM.");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1662,16 +1678,40 @@ public:
|
||||
PRInt64 gcHeapChunkAdmin = numChunks * perChunkAdmin;
|
||||
gcHeapChunkUnused -= gcHeapChunkAdmin;
|
||||
|
||||
DO(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-unused"),
|
||||
// Why 10000x? 100x because it's a percentage, and another 100x
|
||||
// because nsIMemoryReporter requires that for percentage amounts so
|
||||
// they can be fractional.
|
||||
PRInt64 gcHeapUnusedPercentage =
|
||||
(gcHeapChunkUnused + gcHeapArenaUnused) * 10000 /
|
||||
gXPCJSChunkAllocator.GetGCChunkBytesInUse();
|
||||
|
||||
BYTES(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-unused"),
|
||||
JS_GC_HEAP_KIND, gcHeapChunkUnused,
|
||||
"Memory on the garbage-collected JavaScript heap, within chunks, that "
|
||||
"could be holding useful data but currently isn't.");
|
||||
|
||||
DO(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-admin"),
|
||||
BYTES(NS_LITERAL_CSTRING("js-gc-heap-chunk-unused"),
|
||||
nsIMemoryReporter::KIND_OTHER, gcHeapChunkUnused,
|
||||
"The same as 'explicit/js/gc-heap-chunk-unused'. Shown here for "
|
||||
"easy comparison with 'js-gc-heap' and 'js-gc-heap-arena-unused'.");
|
||||
|
||||
BYTES(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-admin"),
|
||||
JS_GC_HEAP_KIND, gcHeapChunkAdmin,
|
||||
"Memory on the garbage-collected JavaScript heap, within chunks, that is "
|
||||
"used to hold internal book-keeping information.");
|
||||
|
||||
BYTES(NS_LITERAL_CSTRING("js-gc-heap-arena-unused"),
|
||||
nsIMemoryReporter::KIND_OTHER, gcHeapArenaUnused,
|
||||
"Memory on the garbage-collected JavaScript heap, within arenas, that "
|
||||
"could be holding useful data but currently isn't. This is the sum of "
|
||||
"all compartments' 'gc-heap/arena-unused' numbers.");
|
||||
|
||||
PERCENTAGE(NS_LITERAL_CSTRING("js-gc-heap-unused-fraction"),
|
||||
nsIMemoryReporter::KIND_OTHER, gcHeapUnusedPercentage,
|
||||
"Fraction of the garbage-collected JavaScript heap that is unused. "
|
||||
"Computed as ('js-gc-heap-chunk-unused' + 'js-gc-heap-arena-unused') / "
|
||||
"'js-gc-heap'.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
@ -48,11 +48,12 @@ var gVerbose = (location.href.split(/[\?,]/).indexOf("verbose") !== -1);
|
||||
|
||||
var gAddedObserver = false;
|
||||
|
||||
const KIND_NONHEAP = Ci.nsIMemoryReporter.KIND_NONHEAP;
|
||||
const KIND_HEAP = Ci.nsIMemoryReporter.KIND_HEAP;
|
||||
const KIND_OTHER = Ci.nsIMemoryReporter.KIND_OTHER;
|
||||
const UNITS_BYTES = Ci.nsIMemoryReporter.UNITS_BYTES;
|
||||
const UNITS_COUNT = Ci.nsIMemoryReporter.UNITS_COUNT;
|
||||
const KIND_NONHEAP = Ci.nsIMemoryReporter.KIND_NONHEAP;
|
||||
const KIND_HEAP = Ci.nsIMemoryReporter.KIND_HEAP;
|
||||
const KIND_OTHER = Ci.nsIMemoryReporter.KIND_OTHER;
|
||||
const UNITS_BYTES = Ci.nsIMemoryReporter.UNITS_BYTES;
|
||||
const UNITS_COUNT = Ci.nsIMemoryReporter.UNITS_COUNT;
|
||||
const UNITS_PERCENTAGE = Ci.nsIMemoryReporter.UNITS_PERCENTAGE;
|
||||
|
||||
const kUnknown = -1; // used for _amount if a memory reporter failed
|
||||
|
||||
@ -258,24 +259,22 @@ function update()
|
||||
content.appendChild(div);
|
||||
}
|
||||
|
||||
// Compare two memory reporter nodes. The primary sort is on the _units
|
||||
// property. The secondary sort is on the _path property if the _units is
|
||||
// UNIT_COUNT, otherwise it is on the _amount property.
|
||||
function cmpAmount(a, b)
|
||||
// Compare two 'explicit' memory reporter nodes.
|
||||
function cmpExplicitReporters(a, b)
|
||||
{
|
||||
if (a._units != b._units) {
|
||||
return a._units - b._units; // use the enum order from nsIMemoryReporter
|
||||
}
|
||||
if (a._units == UNITS_COUNT) {
|
||||
if (a._path < b._path)
|
||||
return -1;
|
||||
if (a._path > b._path)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
assert(a._units === undefined && b._units === undefined,
|
||||
"'explicit' tree nodes must not have _units defined");
|
||||
return b._amount - a._amount;
|
||||
};
|
||||
|
||||
// Compare two memory reporter nodes from the 'other measurements' list.
|
||||
function cmpOtherReporters(a, b)
|
||||
{
|
||||
return a._path < b._path ? -1 :
|
||||
a._path > b._path ? 1 :
|
||||
0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates the text for a single process.
|
||||
*
|
||||
@ -302,6 +301,8 @@ function genProcessText(aProcess, aReporters)
|
||||
* _hasProblem: boolean; (only defined if 'true')
|
||||
* _nMerged: number; (only defined if >= 2)
|
||||
* }
|
||||
* _units isn't needed because it's always UNITS_BYTES for 'explicit'
|
||||
* reporters.
|
||||
*/
|
||||
function buildTree()
|
||||
{
|
||||
@ -319,9 +320,9 @@ function genProcessText(aProcess, aReporters)
|
||||
}
|
||||
|
||||
// We want to process all reporters that begin with 'treeName'. First we
|
||||
// build the tree but only filling in '_name', '_kind', '_units', '_kids',
|
||||
// maybe '_hasReporter' and maybe '_nMerged'. This is done top-down from
|
||||
// the reporters.
|
||||
// build the tree but only fill in '_name', '_kind', '_kids', maybe
|
||||
// '_hasReporter' and maybe '_nMerged'. This is done top-down from the
|
||||
// reporters.
|
||||
var t = {
|
||||
_name: "falseRoot",
|
||||
_kind: KIND_OTHER,
|
||||
@ -330,6 +331,9 @@ function genProcessText(aProcess, aReporters)
|
||||
for (var path in aReporters) {
|
||||
var r = aReporters[path];
|
||||
if (r._path.slice(0, treeName.length) === treeName) {
|
||||
assert(r._kind === KIND_HEAP || r._kind === KIND_NONHEAP,
|
||||
"reporters in the tree must have KIND_HEAP or KIND_NONHEAP");
|
||||
assert(r._units === UNITS_BYTES);
|
||||
var names = r._path.split('/');
|
||||
var u = t;
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
@ -471,7 +475,7 @@ function genProcessText(aProcess, aReporters)
|
||||
*/
|
||||
function filterTree(aT)
|
||||
{
|
||||
aT._kids.sort(cmpAmount);
|
||||
aT._kids.sort(cmpExplicitReporters);
|
||||
|
||||
for (var i = 0; i < aT._kids.length; i++) {
|
||||
if (shouldOmit(aT._kids[i]._amount)) {
|
||||
@ -499,7 +503,7 @@ function genProcessText(aProcess, aReporters)
|
||||
// sum of the omitted sub-trees may be larger than some of the
|
||||
// shown sub-trees.
|
||||
aT._kids[i0] = rSub;
|
||||
aT._kids.sort(cmpAmount);
|
||||
aT._kids.sort(cmpExplicitReporters);
|
||||
break;
|
||||
}
|
||||
filterTree(aT._kids[i]);
|
||||
@ -530,9 +534,10 @@ function genProcessText(aProcess, aReporters)
|
||||
function formatReporterAmount(aReporter)
|
||||
{
|
||||
switch(aReporter._units) {
|
||||
case UNITS_BYTES: return formatBytes(aReporter._amount);
|
||||
case UNITS_COUNT: return formatInt(aReporter._amount);
|
||||
default: return "(???)"
|
||||
case UNITS_BYTES: return formatBytes(aReporter._amount);
|
||||
case UNITS_COUNT: return formatInt(aReporter._amount);
|
||||
case UNITS_PERCENTAGE: return formatPercentage(aReporter._amount);
|
||||
default: return "(???)"
|
||||
}
|
||||
}
|
||||
|
||||
@ -592,6 +597,18 @@ function formatBytes(aBytes)
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage to an appropriate string representation.
|
||||
*
|
||||
* @param aPerc100x
|
||||
* The percentage, multiplied by 100 (see nsIMemoryReporter)
|
||||
* @return The string representation
|
||||
*/
|
||||
function formatPercentage(aPerc100x)
|
||||
{
|
||||
return (aPerc100x / 100).toFixed(2) + "%";
|
||||
}
|
||||
|
||||
/**
|
||||
* Right-justifies a string in a field of a given width, padding as necessary
|
||||
*
|
||||
@ -879,12 +896,14 @@ function genOtherText(aReporters)
|
||||
}
|
||||
}
|
||||
}
|
||||
rArray.sort(cmpAmount);
|
||||
rArray.sort(cmpOtherReporters);
|
||||
|
||||
// Generate text for the not-yet-printed values.
|
||||
var text = "";
|
||||
for (var i = 0; i < rArray.length; i++) {
|
||||
var elem = rArray[i];
|
||||
assert(elem._kind === KIND_OTHER,
|
||||
"elem._kind is not KIND_OTHER for " + elem._path);
|
||||
text += genMrValueText(
|
||||
pad(formatReporterAmount(elem), maxAmountLength, ' ')) + " ";
|
||||
text += genMrNameText(elem._kind, elem._description, elem._path,
|
||||
@ -898,6 +917,13 @@ function genOtherText(aReporters)
|
||||
"<pre>" + text + "</pre>\n";
|
||||
}
|
||||
|
||||
function assert(aCond, aMsg)
|
||||
{
|
||||
if (!aCond) {
|
||||
throw("assertion failed: " + aMsg);
|
||||
}
|
||||
}
|
||||
|
||||
function debug(x)
|
||||
{
|
||||
var content = $("content");
|
||||
|
@ -51,8 +51,9 @@
|
||||
const HEAP = Ci.nsIMemoryReporter.KIND_HEAP;
|
||||
const OTHER = Ci.nsIMemoryReporter.KIND_OTHER;
|
||||
|
||||
const BYTES = Ci.nsIMemoryReporter.UNITS_BYTES;
|
||||
const COUNT = Ci.nsIMemoryReporter.UNITS_COUNT;
|
||||
const BYTES = Ci.nsIMemoryReporter.UNITS_BYTES;
|
||||
const COUNT = Ci.nsIMemoryReporter.UNITS_COUNT;
|
||||
const PERCENTAGE = Ci.nsIMemoryReporter.UNITS_PERCENTAGE;
|
||||
|
||||
function f2(aProcess, aPath, aKind, aUnits, aAmount) {
|
||||
return {
|
||||
@ -100,8 +101,10 @@
|
||||
{ collectReports: function(cbObj, closure) {
|
||||
function f(p, k, u, a) { cbObj.callback("", p, k, u, a, "(desc)", closure); }
|
||||
f("explicit/g", HEAP, BYTES, 14 * MB); // internal
|
||||
f("other2", OTHER, BYTES, 222 * MB);
|
||||
f("other3", OTHER, COUNT, 777);
|
||||
f("other2", OTHER, BYTES, 222 * MB);
|
||||
f("perc2", OTHER, PERCENTAGE, 10000);
|
||||
f("perc1", OTHER, PERCENTAGE, 4567);
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -192,11 +195,13 @@ Explicit Allocations\n\
|
||||
\n\
|
||||
Other Measurements\n\
|
||||
500.00 MB -- heap-allocated\n\
|
||||
222.00 MB -- other2\n\
|
||||
111.00 MB -- other1\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\
|
||||
(???) -- unknown-unit\n\
|
||||
\n\
|
||||
2nd Process\n\
|
||||
@ -211,10 +216,10 @@ Explicit Allocations\n\
|
||||
└────101.00 MB (10.10%) -- heap-unclassified\n\
|
||||
\n\
|
||||
Other Measurements\n\
|
||||
1,000.00 MB -- heap-allocated\n\
|
||||
666.00 MB -- danger<script>window.alert(1)</script>\n\
|
||||
111.00 MB -- other1\n\
|
||||
1,000.00 MB -- heap-allocated\n\
|
||||
100.00 MB -- heap-unallocated\n\
|
||||
111.00 MB -- other1\n\
|
||||
\n\
|
||||
3rd Process\n\
|
||||
\n\
|
||||
@ -263,11 +268,13 @@ Explicit Allocations\n\
|
||||
\n\
|
||||
Other Measurements\n\
|
||||
524,288,000 B -- heap-allocated\n\
|
||||
232,783,872 B -- other2\n\
|
||||
116,391,936 B -- other1\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\
|
||||
(???) -- unknown-unit\n\
|
||||
\n\
|
||||
2nd Process\n\
|
||||
@ -282,10 +289,10 @@ Explicit Allocations\n\
|
||||
└────105,906,176 B (10.10%) -- heap-unclassified\n\
|
||||
\n\
|
||||
Other Measurements\n\
|
||||
1,048,576,000 B -- heap-allocated\n\
|
||||
698,351,616 B -- danger<script>window.alert(1)</script>\n\
|
||||
116,391,936 B -- other1\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\
|
||||
|
@ -140,9 +140,17 @@ interface nsIMemoryReporter : nsISupports
|
||||
* has occurred since the application started up. For instance, a
|
||||
* reporter reporting the number of page faults since startup should have
|
||||
* units UNITS_COUNT.
|
||||
*
|
||||
* - PERCENTAGE: The amount contains a fraction that should be expressed as
|
||||
* a percentage. NOTE! The |amount| field should be given a value 100x
|
||||
* the actual percentage; this number will be divided by 100 when shown.
|
||||
* This allows a fractional percentage to be shown even though |amount| is
|
||||
* an integer. E.g. if the actual percentage is 12.34%, |amount| should
|
||||
* be 1234.
|
||||
*/
|
||||
const PRInt32 UNITS_BYTES = 0;
|
||||
const PRInt32 UNITS_COUNT = 1;
|
||||
const PRInt32 UNITS_PERCENTAGE = 2;
|
||||
|
||||
/*
|
||||
* The units on the reporter's amount. See UNITS_* above.
|
||||
|
Loading…
Reference in New Issue
Block a user