mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1134255 - Add breakdown of allocated and unused GC things by kind in memory reports r=njn
--HG-- extra : rebase_source : aaec1857d252090c2aea9fc8e45a2a82ac492b6c
This commit is contained in:
parent
09e06bd652
commit
439686762a
@ -435,12 +435,66 @@ struct RuntimeSizes
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
||||
struct GCThingSizes
|
||||
{
|
||||
#define FOR_EACH_SIZE(macro) \
|
||||
macro(_, _, object) \
|
||||
macro(_, _, script) \
|
||||
macro(_, _, lazyScript) \
|
||||
macro(_, _, shape) \
|
||||
macro(_, _, baseShape) \
|
||||
macro(_, _, objectGroup) \
|
||||
macro(_, _, string) \
|
||||
macro(_, _, symbol) \
|
||||
macro(_, _, jitcode) \
|
||||
|
||||
GCThingSizes()
|
||||
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||
dummy()
|
||||
{}
|
||||
|
||||
GCThingSizes(GCThingSizes &&other)
|
||||
: FOR_EACH_SIZE(COPY_OTHER_SIZE)
|
||||
dummy()
|
||||
{}
|
||||
|
||||
void addToKind(JSGCTraceKind kind, intptr_t n) {
|
||||
switch (kind) {
|
||||
case JSTRACE_OBJECT: object += n; break;
|
||||
case JSTRACE_STRING: string += n; break;
|
||||
case JSTRACE_SYMBOL: symbol += n; break;
|
||||
case JSTRACE_SCRIPT: script += n; break;
|
||||
case JSTRACE_SHAPE: shape += n; break;
|
||||
case JSTRACE_BASE_SHAPE: baseShape += n; break;
|
||||
case JSTRACE_JITCODE: jitcode += n; break;
|
||||
case JSTRACE_LAZY_SCRIPT: lazyScript += n; break;
|
||||
case JSTRACE_OBJECT_GROUP: objectGroup += n; break;
|
||||
default:
|
||||
MOZ_CRASH("Bad trace kind for GCThingSizes");
|
||||
}
|
||||
}
|
||||
|
||||
void addSizes(const GCThingSizes &other) {
|
||||
FOR_EACH_SIZE(ADD_OTHER_SIZE)
|
||||
}
|
||||
|
||||
size_t totalSize() const {
|
||||
size_t n = 0;
|
||||
FOR_EACH_SIZE(ADD_SIZE_TO_N)
|
||||
return n;
|
||||
}
|
||||
|
||||
FOR_EACH_SIZE(DECL_SIZE)
|
||||
int dummy; // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
||||
struct ZoneStats
|
||||
{
|
||||
#define FOR_EACH_SIZE(macro) \
|
||||
macro(Other, IsLiveGCThing, symbolsGCHeap) \
|
||||
macro(Other, NotLiveGCThing, gcHeapArenaAdmin) \
|
||||
macro(Other, NotLiveGCThing, unusedGCThings) \
|
||||
macro(Other, IsLiveGCThing, lazyScriptsGCHeap) \
|
||||
macro(Other, NotLiveGCThing, lazyScriptsMallocHeap) \
|
||||
macro(Other, IsLiveGCThing, jitCodesGCHeap) \
|
||||
@ -451,6 +505,7 @@ struct ZoneStats
|
||||
|
||||
ZoneStats()
|
||||
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||
unusedGCThings(),
|
||||
stringInfo(),
|
||||
extra(),
|
||||
allStrings(nullptr),
|
||||
@ -460,6 +515,7 @@ struct ZoneStats
|
||||
|
||||
ZoneStats(ZoneStats &&other)
|
||||
: FOR_EACH_SIZE(COPY_OTHER_SIZE)
|
||||
unusedGCThings(mozilla::Move(other.unusedGCThings)),
|
||||
stringInfo(mozilla::Move(other.stringInfo)),
|
||||
extra(other.extra),
|
||||
allStrings(other.allStrings),
|
||||
@ -482,6 +538,7 @@ struct ZoneStats
|
||||
void addSizes(const ZoneStats &other) {
|
||||
MOZ_ASSERT(isTotals);
|
||||
FOR_EACH_SIZE(ADD_OTHER_SIZE)
|
||||
unusedGCThings.addSizes(other.unusedGCThings);
|
||||
stringInfo.add(other.stringInfo);
|
||||
}
|
||||
|
||||
@ -496,6 +553,7 @@ struct ZoneStats
|
||||
void addToTabSizes(JS::TabSizes *sizes) const {
|
||||
MOZ_ASSERT(isTotals);
|
||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||
sizes->add(JS::TabSizes::Other, unusedGCThings.totalSize());
|
||||
stringInfo.addToTabSizes(sizes);
|
||||
}
|
||||
|
||||
@ -504,6 +562,7 @@ struct ZoneStats
|
||||
// measurements of the notable script sources and move them into
|
||||
// |notableStrings|.
|
||||
FOR_EACH_SIZE(DECL_SIZE)
|
||||
GCThingSizes unusedGCThings;
|
||||
StringInfo stringInfo;
|
||||
void *extra; // This field can be used by embedders.
|
||||
|
||||
|
@ -358,7 +358,7 @@ StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
|
||||
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
|
||||
// We do this by setting arenaUnused to maxArenaUnused here, and then
|
||||
// subtracting thingSize for every used cell, in StatsCellCallback().
|
||||
rtStats->currZoneStats->unusedGCThings += allocationSpace;
|
||||
rtStats->currZoneStats->unusedGCThings.addToKind(traceKind, allocationSpace);
|
||||
}
|
||||
|
||||
static CompartmentStats *
|
||||
@ -561,7 +561,7 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
||||
}
|
||||
|
||||
// Yes, this is a subtraction: see StatsArenaCallback() for details.
|
||||
zStats->unusedGCThings -= thingSize;
|
||||
zStats->unusedGCThings.addToKind(traceKind, -thingSize);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -763,7 +763,7 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
|
||||
#ifdef DEBUG
|
||||
// Check that the in-arena measurements look ok.
|
||||
size_t totalArenaSize = rtStats->zTotals.gcHeapArenaAdmin +
|
||||
rtStats->zTotals.unusedGCThings +
|
||||
rtStats->zTotals.unusedGCThings.totalSize() +
|
||||
rtStats->gcHeapGCThings;
|
||||
MOZ_ASSERT(totalArenaSize % gc::ArenaSize == 0);
|
||||
#endif
|
||||
@ -782,7 +782,7 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
|
||||
rtStats->gcHeapUnusedArenas = rtStats->gcHeapChunkTotal -
|
||||
rtStats->gcHeapDecommittedArenas -
|
||||
rtStats->gcHeapUnusedChunks -
|
||||
rtStats->zTotals.unusedGCThings -
|
||||
rtStats->zTotals.unusedGCThings.totalSize() -
|
||||
rtStats->gcHeapChunkAdmin -
|
||||
rtStats->zTotals.gcHeapArenaAdmin -
|
||||
rtStats->gcHeapGCThings;
|
||||
|
@ -1887,6 +1887,19 @@ NS_IMPL_ISUPPORTS(JSMainRuntimeTemporaryPeakReporter, nsIMemoryReporter)
|
||||
rtTotal += amount; \
|
||||
} while (0)
|
||||
|
||||
// Report GC thing bytes.
|
||||
#define MREPORT_BYTES(_path, _kind, _amount, _desc) \
|
||||
do { \
|
||||
size_t amount = _amount; /* evaluate _amount only once */ \
|
||||
nsresult rv; \
|
||||
rv = cb->Callback(EmptyCString(), _path, \
|
||||
nsIMemoryReporter::_kind, \
|
||||
nsIMemoryReporter::UNITS_BYTES, amount, \
|
||||
NS_LITERAL_CSTRING(_desc), closure); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
gcThingTotal += amount; \
|
||||
} while (0)
|
||||
|
||||
MOZ_DEFINE_MALLOC_SIZE_OF(JSMallocSizeOf)
|
||||
|
||||
namespace xpc {
|
||||
@ -1913,8 +1926,8 @@ ReportZoneStats(const JS::ZoneStats &zStats,
|
||||
"Bookkeeping information and alignment padding within GC arenas.");
|
||||
|
||||
ZCREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("unused-gc-things"),
|
||||
zStats.unusedGCThings,
|
||||
"Empty GC thing cells within non-empty arenas.");
|
||||
zStats.unusedGCThings.totalSize(),
|
||||
"Unused GC thing cells within non-empty arenas.");
|
||||
|
||||
ZCREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("lazy-scripts/gc-heap"),
|
||||
zStats.lazyScriptsGCHeap,
|
||||
@ -2926,9 +2939,41 @@ JSReporter::CollectReports(WindowPaths *windowPaths,
|
||||
KIND_OTHER, rtStats.gcHeapUnusedArenas,
|
||||
"The same as 'explicit/js-non-window/gc-heap/unused-arenas'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings,
|
||||
"The same as 'js-main-runtime/zones/unused-gc-things'.");
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/objects"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.object,
|
||||
"Unused object cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/strings"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.string,
|
||||
"Unused string cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/symbols"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.symbol,
|
||||
"Unused symbol cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/shapes"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.shape,
|
||||
"Unused shape cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/base-shapes"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.baseShape,
|
||||
"Unused base shape cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/object-groups"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.objectGroup,
|
||||
"Unused object group cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/scripts"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.script,
|
||||
"Unused script cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/lazy-scripts"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.lazyScript,
|
||||
"Unused lazy script cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things/jitcode"),
|
||||
KIND_OTHER, rtStats.zTotals.unusedGCThings.jitcode,
|
||||
"Unused jitcode cells within non-empty arenas.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/chunk-admin"),
|
||||
KIND_OTHER, rtStats.gcHeapChunkAdmin,
|
||||
@ -2938,9 +2983,46 @@ JSReporter::CollectReports(WindowPaths *windowPaths,
|
||||
KIND_OTHER, rtStats.zTotals.gcHeapArenaAdmin,
|
||||
"The same as 'js-main-runtime/zones/gc-heap-arena-admin'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things"),
|
||||
KIND_OTHER, rtStats.gcHeapGCThings,
|
||||
"GC things: objects, strings, scripts, etc.");
|
||||
size_t gcThingTotal = 0;
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/objects"),
|
||||
KIND_OTHER, rtStats.cTotals.classInfo.objectsGCHeap,
|
||||
"Used object cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/strings"),
|
||||
KIND_OTHER, rtStats.zTotals.stringInfo.sizeOfLiveGCThings(),
|
||||
"Used string cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/symbols"),
|
||||
KIND_OTHER, rtStats.zTotals.symbolsGCHeap,
|
||||
"Used symbol cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/shapes"),
|
||||
KIND_OTHER,
|
||||
rtStats.cTotals.classInfo.shapesGCHeapTree + rtStats.cTotals.classInfo.shapesGCHeapDict,
|
||||
"Used shape cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/base-shapes"),
|
||||
KIND_OTHER, rtStats.cTotals.classInfo.shapesGCHeapBase,
|
||||
"Used base shape cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/object-groups"),
|
||||
KIND_OTHER, rtStats.zTotals.objectGroupsGCHeap,
|
||||
"Used object group cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/scripts"),
|
||||
KIND_OTHER, rtStats.cTotals.scriptsGCHeap,
|
||||
"Used script cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/lazy-scripts"),
|
||||
KIND_OTHER, rtStats.zTotals.lazyScriptsGCHeap,
|
||||
"Used lazy script cells.");
|
||||
|
||||
MREPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things/jitcode"),
|
||||
KIND_OTHER, rtStats.zTotals.jitCodesGCHeap,
|
||||
"Used jitcode cells.");
|
||||
|
||||
MOZ_ASSERT(gcThingTotal == rtStats.gcHeapGCThings);
|
||||
|
||||
// Report xpconnect.
|
||||
|
||||
|
@ -45,10 +45,12 @@
|
||||
|
||||
let vsizeAmounts = [];
|
||||
let residentAmounts = [];
|
||||
let jsGcHeapAmounts = [];
|
||||
let heapAllocatedAmounts = [];
|
||||
let storageSqliteAmounts = [];
|
||||
|
||||
let jsGcHeapUsedGcThingsTotal = 0;
|
||||
let jsGcHeapUsedGcThings = {};
|
||||
|
||||
let present = {}
|
||||
|
||||
// Generate a long, random string. We'll check that this string is
|
||||
@ -79,8 +81,9 @@
|
||||
vsizeAmounts.push(aAmount);
|
||||
} else if (aPath === "resident") {
|
||||
residentAmounts.push(aAmount);
|
||||
} else if (aPath === "js-main-runtime-gc-heap-committed/used/gc-things") {
|
||||
jsGcHeapAmounts.push(aAmount);
|
||||
} else if (aPath.search(/^js-main-runtime-gc-heap-committed\/used\/gc-things\//) >= 0) {
|
||||
jsGcHeapUsedGcThingsTotal += aAmount;
|
||||
jsGcHeapUsedGcThings[aPath] = (jsGcHeapUsedGcThings[aPath] | 0) + 1;
|
||||
} else if (aPath === "heap-allocated") {
|
||||
heapAllocatedAmounts.push(aAmount);
|
||||
} else if (aPath === "storage-sqlite") {
|
||||
@ -201,13 +204,20 @@
|
||||
mgr.getReportsForThisProcess(handleReportAnonymized, null,
|
||||
/* anonymize = */ true);
|
||||
|
||||
function checkSizeReasonable(aName, aAmount)
|
||||
{
|
||||
// Check the size is reasonable -- i.e. not ridiculously large or small.
|
||||
ok(100 * 1000 <= aAmount && aAmount <= 10 * 1000 * 1000 * 1000,
|
||||
aName + "'s size is reasonable");
|
||||
}
|
||||
|
||||
function checkSpecialReport(aName, aAmounts, aCanBeUnreasonable)
|
||||
{
|
||||
ok(aAmounts.length == 1, aName + " has " + aAmounts.length + " report");
|
||||
let n = aAmounts[0];
|
||||
// Check the size is reasonable -- i.e. not ridiculously large or small.
|
||||
ok((100 * 1000 <= n && n <= 10 * 1000 * 1000 * 1000) || aCanBeUnreasonable,
|
||||
aName + "'s size is reasonable");
|
||||
if (!aCanBeUnreasonable) {
|
||||
checkSizeReasonable(aName, n);
|
||||
}
|
||||
}
|
||||
|
||||
// If mgr.explicit failed, we won't have "heap-allocated" either.
|
||||
@ -217,7 +227,12 @@
|
||||
// vsize may be unreasonable if ASAN is enabled
|
||||
checkSpecialReport("vsize", vsizeAmounts, /*canBeUnreasonable*/true);
|
||||
checkSpecialReport("resident", residentAmounts);
|
||||
checkSpecialReport("js-main-runtime-gc-heap-committed/used/gc-things", jsGcHeapAmounts);
|
||||
|
||||
for (var reporter in jsGcHeapUsedGcThings) {
|
||||
ok(jsGcHeapUsedGcThings[reporter] == 1);
|
||||
}
|
||||
checkSizeReasonable("js-main-runtime-gc-heap-committed/used/gc-things",
|
||||
jsGcHeapUsedGcThingsTotal);
|
||||
|
||||
ok(present.jsNonWindowCompartments, "js-non-window compartments are present");
|
||||
ok(present.windowObjectsJsCompartments, "window-objects/.../js compartments are present");
|
||||
|
Loading…
Reference in New Issue
Block a user