Bug 748440 - Part 1: Add heap-committed-unused and heap-committed-unused-ratio memory reporters, and rename some JS memory reporters to match. Also add back the js-gc-heap memory reporter. r=njn
authorJustin Lebar <justin.lebar@gmail.com>
Mon, 30 Apr 2012 14:27:15 -0400
changeset 92809 f5a301fe9ba5548c629389f45639f1d741355666
parent 92808 ecfa1fd40096332ef103a4d57eb7265fd5c2aaee
child 92810 d7db4957bb753e1f953cec36aa534dc12c8ff02d
push id22595
push usereakhgari@mozilla.com
push dateThu, 03 May 2012 04:00:15 +0000
treeherdermozilla-central@807403a04a6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs748440
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 748440 - Part 1: Add heap-committed-unused and heap-committed-unused-ratio memory reporters, and rename some JS memory reporters to match. Also add back the js-gc-heap memory reporter. r=njn
browser/components/privatebrowsing/test/unit/test_privatebrowsing_autostart.js
browser/components/privatebrowsing/test/unit/test_privatebrowsingwrapper_autostart.js
js/public/MemoryMetrics.h
js/src/MemoryMetrics.cpp
js/xpconnect/src/XPCJSRuntime.cpp
security/manager/ssl/src/nsNSSIOLayer.cpp
security/manager/ssl/src/nsNSSIOLayer.h
xpcom/base/nsIMemoryReporter.idl
xpcom/base/nsMemoryReporterManager.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -117,17 +117,16 @@ struct RuntimeStats
       , gcHeapCommitted(0)
       , gcHeapUnused(0)
       , gcHeapChunkCleanUnused(0)
       , gcHeapChunkDirtyUnused(0)
       , gcHeapChunkCleanDecommitted(0)
       , gcHeapChunkDirtyDecommitted(0)
       , gcHeapArenaUnused(0)
       , gcHeapChunkAdmin(0)
-      , gcHeapFragmentationPercentage(0)
       , totalObjects(0)
       , totalShapes(0)
       , totalScripts(0)
       , totalStrings(0)
 #ifdef JS_METHODJIT
       , totalMjit(0)
 #endif
       , totalTypeInference(0)
@@ -149,17 +148,16 @@ struct RuntimeStats
     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 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
@@ -277,24 +277,16 @@ CollectRuntimeStats(JSRuntime *rt, Runti
     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->gcHeapFragmentationPercentage = (rtStats->gcHeapChunkCleanUnused +
-                                              rtStats->gcHeapChunkDirtyUnused +
-                                              rtStats->gcHeapArenaUnused) * 10000 /
-                                              rtStats->gcHeapCommitted;
-
     return true;
 }
 
 static void
 ExplicitNonHeapCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
 {
 #ifdef JS_METHODJIT
     size_t *n = static_cast<size_t *>(data);
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1245,16 +1245,32 @@ GetCompartmentName(JSCompartment *c, boo
         // (such as about:memory) have to undo this change.
         name.ReplaceChar('/', '\\');
     } else {
         name.AssignLiteral("null-principal");
     }
 }
 
 static PRInt64
+GetGCChunkTotalBytes()
+{
+    JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
+    return PRInt64(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * js::gc::ChunkSize;
+}
+
+// Telemetry relies on this memory reporter being a single-reporter (rather
+// than part of the "js" multi-reporter, which is too slow to run during a
+// telemetry ping).
+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()
 {
@@ -1761,45 +1777,50 @@ public:
         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_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused"),
+        REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed-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'.");
 
+        // Why 10000x?  100x because it's a percentage, and another 100x
+        // because nsIMemoryReporter requires that for UNITS_PERCENTAGE
+        // reporters so we can get two decimal places out of the integer value.
+        REPORT(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed-unused-ratio"),
+               nsIMemoryReporter::KIND_OTHER,
+               nsIMemoryReporter::UNITS_PERCENTAGE,
+               (PRInt64) 10000 * rtStats.gcHeapUnused /
+                   ((double) rtStats.gcHeapCommitted - rtStats.gcHeapUnused),
+               "Ratio of committed, unused bytes to allocated bytes; i.e. "
+               "'gc-heap-committed-unused' / 'gc-heap-allocated'.  This "
+               "measures the overhead of the GC heap allocator relative to the "
+               "amount of memory allocated.");
+
         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.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,
@@ -2002,16 +2023,17 @@ 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;
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -192,16 +192,18 @@ interface nsIMemoryReporter : nsISupport
    *    never decrease over the lifetime of the application.
    *
    *  - 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.
+   *
+   *    Values greater than 100% are allowed.
    */
   const PRInt32 UNITS_BYTES = 0;
   const PRInt32 UNITS_COUNT = 1;
   const PRInt32 UNITS_COUNT_CUMULATIVE = 2;
   const PRInt32 UNITS_PERCENTAGE = 3;
 
   /*
    * The units on the reporter's amount.  See UNITS_* above.
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -361,17 +361,17 @@ NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Pa
  ** to obtain info on total memory in use (that we know about,
  ** at least -- on OSX, there are sometimes other zones in use).
  **/
 
 #if HAVE_JEMALLOC_STATS
 
 #define HAVE_HEAP_ALLOCATED_REPORTERS 1
 
-static PRInt64 GetHeapUnallocated()
+static PRInt64 GetHeapUnused()
 {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
     return (PRInt64) (stats.mapped - stats.allocated);
 }
 
 static PRInt64 GetHeapAllocated()
 {
@@ -382,21 +382,29 @@ static PRInt64 GetHeapAllocated()
 
 static PRInt64 GetHeapCommitted()
 {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
     return (PRInt64) stats.committed;
 }
 
-static PRInt64 GetHeapCommittedFragmentation()
+static PRInt64 GetHeapCommittedUnused()
 {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
-    return (PRInt64) (10000 * (1 - stats.allocated / (double)stats.committed));
+    return stats.committed - stats.allocated;
+}
+
+static PRInt64 GetHeapCommittedUnusedRatio()
+{
+    jemalloc_stats_t stats;
+    jemalloc_stats(&stats);
+    return (PRInt64) 10000 * (stats.committed - stats.allocated) /
+                              ((double)stats.allocated);
 }
 
 static PRInt64 GetHeapDirty()
 {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
     return (PRInt64) stats.dirty;
 }
@@ -408,42 +416,51 @@ NS_MEMORY_REPORTER_IMPLEMENT(HeapCommitt
     GetHeapCommitted,
     "Memory mapped by the heap allocator that is committed, i.e. in physical "
     "memory or paged to disk.  When heap-committed is larger than "
     "heap-allocated, the difference between the two values is likely due to "
     "external fragmentation; that is, the allocator allocated a large block of "
     "memory and is unable to decommit it because a small part of that block is "
     "currently in use.")
 
-NS_MEMORY_REPORTER_IMPLEMENT(HeapCommittedFragmentation,
-    "heap-committed-fragmentation",
+NS_MEMORY_REPORTER_IMPLEMENT(HeapCommittedUnused,
+    "heap-committed-unused",
+    KIND_OTHER,
+    UNITS_BYTES,
+    GetHeapCommittedUnused,
+    "Committed bytes which do not correspond to an active allocation; i.e., "
+    "'heap-committed' - 'heap-allocated'.  Although the allocator will waste some "
+    "space under any circumstances, a large value here may indicate that the "
+    "heap is highly fragmented.")
+
+NS_MEMORY_REPORTER_IMPLEMENT(HeapCommittedUnusedRatio,
+    "heap-committed-unused-ratio",
     KIND_OTHER,
     UNITS_PERCENTAGE,
-    GetHeapCommittedFragmentation,
-    "Fraction of committed bytes which do not correspond to an active "
-    "allocation; i.e., 1 - (heap-allocated / heap-committed).  Although the "
-    "allocator will waste some space under any circumstances, a large value here "
-    "may indicate that the heap is highly fragmented.")
+    GetHeapCommittedUnusedRatio,
+    "Ratio of committed, unused bytes to allocated bytes; i.e., "
+    "'heap-committed-unused' / 'heap-allocated'.  This measures the overhead "
+    "of the heap allocator relative to amount of memory allocated.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(HeapDirty,
     "heap-dirty",
     KIND_OTHER,
     UNITS_BYTES,
     GetHeapDirty,
     "Memory which the allocator could return to the operating system, but "
     "hasn't.  The allocator keeps this memory around as an optimization, so it "
     "doesn't have to ask the OS the next time it needs to fulfill a request. "
     "This value is typically not larger than a few megabytes.")
 
 #elif defined(XP_MACOSX) && !defined(MOZ_MEMORY)
 #include <malloc/malloc.h>
 
 #define HAVE_HEAP_ALLOCATED_REPORTERS 1
 
-static PRInt64 GetHeapUnallocated()
+static PRInt64 GetHeapUnused()
 {
     struct mstats stats = mstats();
     return stats.bytes_total - stats.bytes_used;
 }
 
 static PRInt64 GetHeapAllocated()
 {
     struct mstats stats = mstats();
@@ -484,24 +501,24 @@ NS_MEMORY_REPORTER_IMPLEMENT(HeapZone0Us
     GetHeapZone0Used,
     "Memory mapped by the heap allocator in the default zone that is "
     "allocated to the application.")
 #endif  // MOZ_DMD
 
 #endif
 
 #ifdef HAVE_HEAP_ALLOCATED_REPORTERS
-NS_MEMORY_REPORTER_IMPLEMENT(HeapUnallocated,
-    "heap-unallocated",
+NS_MEMORY_REPORTER_IMPLEMENT(HeapUnused,
+    "heap-unused",
     KIND_OTHER,
     UNITS_BYTES,
-    GetHeapUnallocated,
+    GetHeapUnused,
     "Memory mapped by the heap allocator that is not part of an active "
-    "allocation. Much of this memory may be uncommitted -- that is, it does "
-    "not take up space in physical memory or in the swap file.")
+    "allocation. Much of this memory may be uncommitted -- that is, it does not "
+    "take up space in physical memory or in the swap file.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(HeapAllocated,
     "heap-allocated",
     KIND_OTHER,
     UNITS_BYTES,
     GetHeapAllocated,
     "Memory mapped by the heap allocator that is currently allocated to the "
     "application.  This may exceed the amount of memory requested by the "
@@ -561,17 +578,17 @@ nsMemoryReporterManager::Init()
     if (!jemalloc_stats)
         return NS_ERROR_FAILURE;
 #endif
 
 #define REGISTER(_x)  RegisterReporter(new NS_MEMORY_REPORTER_NAME(_x))
 
 #ifdef HAVE_HEAP_ALLOCATED_REPORTERS
     REGISTER(HeapAllocated);
-    REGISTER(HeapUnallocated);
+    REGISTER(HeapUnused);
 #endif
 
 #ifdef HAVE_EXPLICIT_REPORTER
     REGISTER(Explicit);
 #endif
 
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
     REGISTER(Vsize);
@@ -584,17 +601,17 @@ nsMemoryReporterManager::Init()
 #endif
 
 #ifdef HAVE_PRIVATE_REPORTER
     REGISTER(Private);
 #endif
 
 #if defined(HAVE_JEMALLOC_STATS)
     REGISTER(HeapCommitted);
-    REGISTER(HeapCommittedFragmentation);
+    REGISTER(HeapCommittedUnusedRatio);
     REGISTER(HeapDirty);
 #elif defined(HAVE_HEAP_ZONE0_REPORTERS)
     REGISTER(HeapZone0Committed);
     REGISTER(HeapZone0Used);
 #endif
 
     REGISTER(AtomTable);