Bug 741378 - Rejigger the js memory reporters to match jemalloc's. r=njn
authorJustin Lebar <justin.lebar@gmail.com>
Mon, 16 Apr 2012 12:20:54 +1000
changeset 95047 48315737bd3f0ca1718195129157b301eaf0b44f
parent 95046 d3b5f1d1dd11fbb1500d915be861af2af5fb042d
child 95048 29c2bb6184b6abeb1a390cfc77e20fc9412726b7
push idunknown
push userunknown
push dateunknown
reviewersnjn
bugs741378
milestone14.0a1
Bug 741378 - Rejigger the js memory reporters to match jemalloc's. r=njn
js/public/MemoryMetrics.h
js/src/MemoryMetrics.cpp
js/xpconnect/src/XPCJSRuntime.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -109,23 +109,25 @@ struct RuntimeStats
       , runtimeAtomsTable(0)
       , runtimeContexts(0)
       , runtimeNormal(0)
       , runtimeTemporary(0)
       , runtimeRegexpCode(0)
       , runtimeStackCommitted(0)
       , runtimeGCMarker(0)
       , gcHeapChunkTotal(0)
+      , gcHeapCommitted(0)
+      , gcHeapUnused(0)
       , gcHeapChunkCleanUnused(0)
       , gcHeapChunkDirtyUnused(0)
       , gcHeapChunkCleanDecommitted(0)
       , gcHeapChunkDirtyDecommitted(0)
       , gcHeapArenaUnused(0)
       , gcHeapChunkAdmin(0)
-      , gcHeapUnusedPercentage(0)
+      , gcHeapFragmentationPercentage(0)
       , totalObjects(0)
       , totalShapes(0)
       , totalScripts(0)
       , totalStrings(0)
 #ifdef JS_METHODJIT
       , totalMjit(0)
 #endif
       , totalTypeInference(0)
@@ -139,23 +141,25 @@ struct RuntimeStats
     size_t runtimeAtomsTable;
     size_t runtimeContexts;
     size_t runtimeNormal;
     size_t runtimeTemporary;
     size_t runtimeRegexpCode;
     size_t runtimeStackCommitted;
     size_t runtimeGCMarker;
     size_t gcHeapChunkTotal;
+    size_t gcHeapCommitted;
+    size_t gcHeapUnused;
     size_t gcHeapChunkCleanUnused;
     size_t gcHeapChunkDirtyUnused;
     size_t gcHeapChunkCleanDecommitted;
     size_t gcHeapChunkDirtyDecommitted;
     size_t gcHeapArenaUnused;
     size_t gcHeapChunkAdmin;
-    size_t gcHeapUnusedPercentage;
+    size_t gcHeapFragmentationPercentage;
     size_t totalObjects;
     size_t totalShapes;
     size_t totalScripts;
     size_t totalStrings;
 #ifdef JS_METHODJIT
     size_t totalMjit;
 #endif
     size_t totalTypeInference;
--- a/js/src/MemoryMetrics.cpp
+++ b/js/src/MemoryMetrics.cpp
@@ -269,25 +269,31 @@ CollectRuntimeStats(JSRuntime *rt, Runti
     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;
+
     // 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;
+    rtStats->gcHeapFragmentationPercentage = (rtStats->gcHeapChunkCleanUnused +
+                                              rtStats->gcHeapChunkDirtyUnused +
+                                              rtStats->gcHeapArenaUnused) * 10000 /
+                                              rtStats->gcHeapCommitted;
 
     return true;
 }
 
 static void
 ExplicitNonHeapCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
 {
 #ifdef JS_METHODJIT
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1245,34 +1245,16 @@ GetCompartmentName(JSCompartment *c, boo
         // treated as path separators.  Users of the reporters
         // (such as about:memory) have to undo this change.
         name.ReplaceChar('/', '\\');
     } else {
         name.AssignLiteral("null-principal");
     }
 }
 
-// We have per-compartment GC heap totals, so we can't put the total GC heap
-// size in the explicit allocations tree.  But it's a useful figure, so put it
-// in the "others" list.
-
-static PRInt64
-GetGCChunkTotalBytes()
-{
-    JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
-    return PRInt64(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * js::gc::ChunkSize;
-}
-
-NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSGCHeap,
-                             "js-gc-heap",
-                             KIND_OTHER,
-                             nsIMemoryReporter::UNITS_BYTES,
-                             GetGCChunkTotalBytes,
-                             "Memory used by the garbage-collected JavaScript heap.")
-
 static PRInt64
 GetJSSystemCompartmentCount()
 {
     return JS::SystemCompartmentCount(nsXPConnect::GetRuntimeInstance()->GetJSRuntime());
 }
 
 static PRInt64
 GetJSUserCompartmentCount()
@@ -1385,17 +1367,17 @@ ReportCompartmentStats(const JS::Compart
                        nsISupports *closure, size_t *gcTotalOut)
 {
     size_t gcTotal = 0;
 
     REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/headers"),
                      cStats.gcHeapArenaHeaders,
                      "Memory on the compartment's garbage-collected JavaScript "
                      "heap, within arenas, that is used to hold internal "
-                     "book-keeping information.");
+                     "bookkeeping information.");
 
     REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/padding"),
                      cStats.gcHeapArenaPadding,
                      "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.");
 
@@ -1623,17 +1605,17 @@ ReportJSRuntimeExplicitTreeStats(const J
     REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-decommitted"),
                     rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
                     "Memory in the address space of the garbage-collected "
                     "JavaScript heap that is currently returned to the OS.");
 
     REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-admin"),
                     rtStats.gcHeapChunkAdmin,
                     "Memory on the garbage-collected JavaScript heap, within "
-                    "chunks, that is used to hold internal book-keeping "
+                    "chunks, that is used to hold internal bookkeeping "
                     "information.");
 
     // gcTotal is the sum of everything we've reported for the GC heap.  It
     // should equal rtStats.gcHeapChunkTotal.
     JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal);
 
     return NS_OK;
 }
@@ -1774,39 +1756,58 @@ public:
 
         REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-clean-unused"),
                      nsIMemoryReporter::KIND_OTHER,
                      rtStats.gcHeapChunkCleanUnused,
                      "The same as 'explicit/js/gc-heap-chunk-clean-unused'.  "
                      "Shown here for easy comparison with other 'js-gc' "
                      "reporters.");
 
-        REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"),
-                     nsIMemoryReporter::KIND_OTHER,
-                     rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
-                     "The same as 'explicit/js/gc-heap-decommitted'.  Shown "
-                     "here for easy comparison with other 'js-gc' reporters.");
-
         REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-arena-unused"),
                      nsIMemoryReporter::KIND_OTHER,
                      rtStats.gcHeapArenaUnused,
                      "Memory on the main JSRuntime's 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.");
 
-        REPORT(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-fraction"),
+        REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused"),
+                     nsIMemoryReporter::KIND_OTHER,
+                     rtStats.gcHeapUnused,
+                     "Amount of the GC heap that's committed, but that is "
+                     "neither part of an active allocation nor being used for "
+                     "bookkeeping.  Equal to 'gc-heap-chunk-dirty-unused' + "
+                     "'gc-heap-chunk-clean-unused' + 'gc-heap-arena-unused'.");
+
+        REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed"),
+                     nsIMemoryReporter::KIND_OTHER,
+                     rtStats.gcHeapCommitted,
+                     "Committed memory (i.e., in physical memory or swap) "
+                     "used by the garbage-collected JavaScript heap.");
+
+        REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-allocated"),
+                     nsIMemoryReporter::KIND_OTHER,
+                     (rtStats.gcHeapCommitted - rtStats.gcHeapUnused),
+                     "Amount of the GC heap used for active allocations and "
+                     "bookkeeping.  This is calculated as 'gc-heap-committed' "
+                     "- 'gc-heap-unused'.");
+
+        REPORT(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-fragmentation"),
                nsIMemoryReporter::KIND_OTHER,
                nsIMemoryReporter::UNITS_PERCENTAGE,
-               rtStats.gcHeapUnusedPercentage,
-               "Fraction of the main JSRuntime's garbage-collected JavaScript "
-               "heap that is unused. Computed as "
-               "('js-gc-heap-chunk-clean-unused' + "
-               "'js-gc-heap-chunk-dirty-unused' + 'js-gc-heap-decommitted' + "
-               "'js-gc-heap-arena-unused') / 'js-gc-heap'.");
+               rtStats.gcHeapFragmentationPercentage,
+               "Fraction of the committed part of the main JSRuntime's "
+               "garbage-collected heap that is unused. Computed as "
+               "'gc-heap-unused' / 'gc-heap-committed'.");
+
+        REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"),
+                     nsIMemoryReporter::KIND_OTHER,
+                     rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
+                     "The same as 'explicit/js/gc-heap-decommitted'.  Shown "
+                     "here for easy comparison with other 'js-gc' reporters.");
 
         REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-objects"),
                      nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects,
                      "Memory used for all object-related data in the main "
                      "JSRuntime. This is the sum of all compartments' "
                      "'gc-heap/objects-non-function', "
                      "'gc-heap/objects-function' and 'object-slots' numbers.");
 
@@ -2003,17 +2004,16 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
                               xpc::WrapperFactory::PrepareForWrapping);
     js::SetPreserveWrapperCallback(mJSRuntime, PreserveWrapper);
 #ifdef MOZ_CRASHREPORTER
     JS_EnumerateDiagnosticMemoryRegions(DiagnosticMemoryCallback);
 #endif
     JS_SetAccumulateTelemetryCallback(mJSRuntime, AccumulateTelemetryCallback);
     js::SetActivityCallback(mJSRuntime, ActivityCallback, this);
         
-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
     NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
     NS_RegisterMemoryMultiReporter(new JSMemoryMultiReporter);
     NS_RegisterMemoryMultiReporter(new JSCompartmentsMultiReporter);
 
     if (!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
                            sizeof(ObjectHolder), 512))
         mJSHolders.ops = nsnull;