CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv) { if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length())) return false; rtStats->gcHeapChunkTotal = size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize; rtStats->gcHeapUnusedChunks = size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize; // This just computes rtStats->gcHeapDecommittedArenas. IterateChunks(rt, rtStats, StatsChunkCallback); // Take the per-compartment measurements. IteratorClosure closure(rtStats, opv); if (!closure.init()) return false; rtStats->runtime.scriptSources = 0; IterateCompartmentsArenasCells(rt, &closure, StatsCompartmentCallback, StatsArenaCallback, StatsCellCallback); // Take the "explicit/js/runtime/" measurements. rt->sizeOfIncludingThis(rtStats->mallocSizeOf, &rtStats->runtime); rtStats->gcHeapGcThings = 0; for (size_t i = 0; i < rtStats->compartmentStatsVector.length(); i++) { CompartmentStats &cStats = rtStats->compartmentStatsVector[i]; rtStats->totals.add(cStats); rtStats->gcHeapGcThings += cStats.gcHeapThingsSize(); } size_t numDirtyChunks = (rtStats->gcHeapChunkTotal - rtStats->gcHeapUnusedChunks) / gc::ChunkSize; size_t perChunkAdmin = sizeof(gc::Chunk) - (sizeof(gc::Arena) * gc::ArenasPerChunk); rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin; rtStats->gcHeapUnusedArenas -= rtStats->gcHeapChunkAdmin; // |gcHeapUnusedArenas| is the only thing left. Compute it in terms of // all the others. See the comment in RuntimeStats for explanation. rtStats->gcHeapUnusedArenas = rtStats->gcHeapChunkTotal - rtStats->gcHeapDecommittedArenas - rtStats->gcHeapUnusedChunks - rtStats->totals.gcHeapUnusedGcThings - rtStats->gcHeapChunkAdmin - rtStats->totals.gcHeapArenaAdmin - rtStats->gcHeapGcThings; return true; }
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats) { if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length())) return false; rtStats->gcHeapChunkCleanDecommitted = rt->gcChunkPool.countCleanDecommittedArenas(rt) * gc::ArenaSize; rtStats->gcHeapChunkCleanUnused = size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize - rtStats->gcHeapChunkCleanDecommitted; rtStats->gcHeapChunkTotal = size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize; IterateCompartmentsArenasCells(rt, rtStats, StatsCompartmentCallback, StatsArenaCallback, StatsCellCallback); IterateChunks(rt, rtStats, StatsChunkCallback); rtStats->runtimeObject = rtStats->mallocSizeOf(rt); rt->sizeOfExcludingThis(rtStats->mallocSizeOf, &rtStats->runtimeNormal, &rtStats->runtimeTemporary, &rtStats->runtimeRegexpCode, &rtStats->runtimeStackCommitted, &rtStats->runtimeGCMarker); rtStats->runtimeAtomsTable = rt->atomState.atoms.sizeOfExcludingThis(rtStats->mallocSizeOf); for (ContextIter acx(rt); !acx.done(); acx.next()) rtStats->runtimeContexts += acx->sizeOfIncludingThis(rtStats->mallocSizeOf); // This is initialized to all bytes stored in used chunks, and then we // subtract used space from it each time around the loop. rtStats->gcHeapChunkDirtyUnused = rtStats->gcHeapChunkTotal - rtStats->gcHeapChunkCleanUnused - rtStats->gcHeapChunkCleanDecommitted - rtStats->gcHeapChunkDirtyDecommitted; for (size_t index = 0; index < rtStats->compartmentStatsVector.length(); index++) { CompartmentStats &cStats = rtStats->compartmentStatsVector[index]; size_t used = cStats.gcHeapArenaHeaders + cStats.gcHeapArenaPadding + cStats.gcHeapArenaUnused + cStats.gcHeapObjectsNonFunction + cStats.gcHeapObjectsFunction + cStats.gcHeapStrings + cStats.gcHeapShapesTree + cStats.gcHeapShapesDict + cStats.gcHeapShapesBase + cStats.gcHeapScripts + cStats.gcHeapTypeObjects + cStats.gcHeapXML; rtStats->gcHeapChunkDirtyUnused -= used; rtStats->gcHeapArenaUnused += cStats.gcHeapArenaUnused; rtStats->totalObjects += cStats.gcHeapObjectsNonFunction + cStats.gcHeapObjectsFunction + cStats.objectSlots + cStats.objectElements + cStats.objectMisc; rtStats->totalShapes += cStats.gcHeapShapesTree + cStats.gcHeapShapesDict + cStats.gcHeapShapesBase + cStats.shapesExtraTreeTables + cStats.shapesExtraDictTables + cStats.shapesCompartmentTables; rtStats->totalScripts += cStats.gcHeapScripts + cStats.scriptData; rtStats->totalStrings += cStats.gcHeapStrings + cStats.stringChars; #ifdef JS_METHODJIT rtStats->totalMjit += cStats.mjitCode + cStats.mjitData; #endif rtStats->totalTypeInference += cStats.gcHeapTypeObjects + cStats.typeInferenceSizes.objects + cStats.typeInferenceSizes.scripts + cStats.typeInferenceSizes.tables; rtStats->totalAnalysisTemp += cStats.typeInferenceSizes.temporary; } size_t numDirtyChunks = (rtStats->gcHeapChunkTotal - rtStats->gcHeapChunkCleanUnused) / gc::ChunkSize; size_t perChunkAdmin = sizeof(gc::Chunk) - (sizeof(gc::Arena) * gc::ArenasPerChunk); rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin; rtStats->gcHeapChunkDirtyUnused -= rtStats->gcHeapChunkAdmin; // Why 10000x? 100x because it's a percentage, and another 100x // because nsIMemoryReporter requires that for percentage amounts so // they can be fractional. rtStats->gcHeapUnusedPercentage = (rtStats->gcHeapChunkCleanUnused + rtStats->gcHeapChunkDirtyUnused + rtStats->gcHeapChunkCleanDecommitted + rtStats->gcHeapChunkDirtyDecommitted + rtStats->gcHeapArenaUnused) * 10000 / rtStats->gcHeapChunkTotal; return true; }
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats) { if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length())) return false; rtStats->gcHeapChunkCleanDecommitted = rt->gcChunkPool.countCleanDecommittedArenas(rt) * gc::ArenaSize; rtStats->gcHeapChunkCleanUnused = size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize - rtStats->gcHeapChunkCleanDecommitted; rtStats->gcHeapChunkTotal = size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize; IterateCompartmentsArenasCells(rt, rtStats, StatsCompartmentCallback, StatsArenaCallback, StatsCellCallback); IterateChunks(rt, rtStats, StatsChunkCallback); rt->sizeOfIncludingThis(rtStats->mallocSizeOf, &rtStats->runtime); // This is initialized to all bytes stored in used chunks, and then we // subtract used space from it each time around the loop. rtStats->gcHeapChunkDirtyUnused = rtStats->gcHeapChunkTotal - rtStats->gcHeapChunkCleanUnused - rtStats->gcHeapChunkCleanDecommitted - rtStats->gcHeapChunkDirtyDecommitted; rtStats->totalMjit = rtStats->runtime.mjitCode; for (size_t index = 0; index < rtStats->compartmentStatsVector.length(); index++) { CompartmentStats &cStats = rtStats->compartmentStatsVector[index]; size_t used = cStats.gcHeapArenaHeaders + cStats.gcHeapArenaPadding + cStats.gcHeapArenaUnused + cStats.gcHeapObjectsNonFunction + cStats.gcHeapObjectsFunction + cStats.gcHeapStrings + cStats.gcHeapShapesTree + cStats.gcHeapShapesDict + cStats.gcHeapShapesBase + cStats.gcHeapScripts + #if JS_HAS_XML_SUPPORT cStats.gcHeapXML + #endif cStats.gcHeapTypeObjects; rtStats->gcHeapChunkDirtyUnused -= used; rtStats->gcHeapArenaUnused += cStats.gcHeapArenaUnused; rtStats->totalObjects += cStats.gcHeapObjectsNonFunction + cStats.gcHeapObjectsFunction + cStats.objectSlots + cStats.objectElements + cStats.objectMisc; rtStats->totalShapes += cStats.gcHeapShapesTree + cStats.gcHeapShapesDict + cStats.gcHeapShapesBase + cStats.shapesExtraTreeTables + cStats.shapesExtraDictTables + cStats.shapesCompartmentTables; rtStats->totalScripts += cStats.gcHeapScripts + cStats.scriptData; rtStats->totalStrings += cStats.gcHeapStrings + cStats.stringChars; rtStats->totalMjit += cStats.mjitData; rtStats->totalTypeInference += cStats.gcHeapTypeObjects + cStats.typeInferenceSizes.objects + cStats.typeInferenceSizes.scripts + cStats.typeInferenceSizes.tables; rtStats->totalAnalysisTemp += cStats.typeInferenceSizes.temporary; } size_t numDirtyChunks = (rtStats->gcHeapChunkTotal - rtStats->gcHeapChunkCleanUnused) / gc::ChunkSize; size_t perChunkAdmin = sizeof(gc::Chunk) - (sizeof(gc::Arena) * gc::ArenasPerChunk); rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin; rtStats->gcHeapChunkDirtyUnused -= rtStats->gcHeapChunkAdmin; rtStats->gcHeapUnused = rtStats->gcHeapChunkDirtyUnused + rtStats->gcHeapChunkCleanUnused + rtStats->gcHeapArenaUnused; rtStats->gcHeapCommitted = rtStats->gcHeapChunkTotal - rtStats->gcHeapChunkCleanDecommitted - rtStats->gcHeapChunkDirtyDecommitted; return true; }