Bug 939385 - Report vsizeMaxContiguous in about:memory and telemetry. a=lsblakk
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 26 Nov 2013 23:05:34 -0500
changeset 166621 d364517977a73340f7be783937dd9e368adc883b
parent 166620 fc8df6e6a54098bee24c5c575beac0af8437e466
child 166622 e7be5919512b829fad0cb81d8768c97ed885240a
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsblakk
bugs939385, 939137
milestone27.0a2
Bug 939385 - Report vsizeMaxContiguous in about:memory and telemetry. a=lsblakk Includes bug 939137.
testing/mochitest/tests/SimpleTest/TestRunner.js
toolkit/components/aboutmemory/tests/test_memoryReporters.xul
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/TelemetryPing.js
xpcom/base/nsIMemoryReporter.idl
xpcom/base/nsMemoryReporterManager.cpp
--- a/testing/mochitest/tests/SimpleTest/TestRunner.js
+++ b/testing/mochitest/tests/SimpleTest/TestRunner.js
@@ -381,32 +381,76 @@ TestRunner.runNextTest = function() {
     }
 };
 
 TestRunner.expectChildProcessCrash = function() {
     TestRunner._expectingProcessCrash = true;
 };
 
 /**
+ * Statistics that we want to retrieve and display after every test is
+ * done.  The keys of this table are intended to be identical to the
+ * relevant attributes of nsIMemoryReporterManager.  However, since
+ * nsIMemoryReporterManager doesn't necessarily support all these
+ * statistics in all build configurations, we also use this table to
+ * tell us whether statistics are supported or not.
+ */
+var MEM_STAT_UNKNOWN = 0;
+var MEM_STAT_UNSUPPORTED = 1;
+var MEM_STAT_SUPPORTED = 2;
+TestRunner._hasMemoryStatistics = {}
+TestRunner._hasMemoryStatistics.vsize = MEM_STAT_UNKNOWN;
+TestRunner._hasMemoryStatistics.vsizeMaxContiguous = MEM_STAT_UNKNOWN;
+TestRunner._hasMemoryStatistics.heapAllocated = MEM_STAT_UNKNOWN;
+
+/**
  * This stub is called by SimpleTest when a test is finished.
 **/
 TestRunner.testFinished = function(tests) {
     // Prevent a test from calling finish() multiple times before we
     // have a chance to unload it.
     if (TestRunner._currentTest == TestRunner._lastTestFinished &&
         !TestRunner._loopIsRestarting) {
         TestRunner.error("TEST-UNEXPECTED-FAIL | " +
                          TestRunner.currentTestURL +
                          " | called finish() multiple times");
         TestRunner.updateUI([{ result: false }]);
         return;
     }
     TestRunner._lastTestFinished = TestRunner._currentTest;
     TestRunner._loopIsRestarting = false;
 
+    var mrm;
+    try {
+	mrm = Cc["@mozilla.org/memory-reporter-manager;1"]
+	    .getService(Ci.nsIMemoryReporterManager);
+    } catch (e) {
+	mrm = SpecialPowers.Cc["@mozilla.org/memory-reporter-manager;1"]
+	                   .getService(SpecialPowers.Ci.nsIMemoryReporterManager);
+    }
+    for (stat in TestRunner._hasMemoryStatistics) {
+        var supported = TestRunner._hasMemoryStatistics[stat];
+        var firstAccess = false;
+        if (supported == MEM_STAT_UNKNOWN) {
+            firstAccess = true;
+            try {
+                var value = mrm[stat];
+                supported = MEM_STAT_SUPPORTED;
+            } catch (e) {
+                supported = MEM_STAT_UNSUPPORTED;
+            }
+            TestRunner._hasMemoryStatistics[stat] = supported;
+        }
+        if (supported == MEM_STAT_SUPPORTED) {
+            TestRunner.log("TEST-INFO | MEMORY STAT " + stat + " after test: " + mrm[stat]);
+        } else if (firstAccess) {
+            TestRunner.log("TEST-INFO | MEMORY STAT " + stat + " not supported in this build configuration.");
+        }
+    }
+
     function cleanUpCrashDumpFiles() {
         if (!SpecialPowers.removeExpectedCrashDumpFiles(TestRunner._expectingProcessCrash)) {
             TestRunner.error("TEST-UNEXPECTED-FAIL | " +
                              TestRunner.currentTestURL +
                              " | This test did not leave any crash dumps behind, but we were expecting some!");
             tests.push({ result: false });
         }
         var unexpectedCrashDumpFiles =
--- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul
+++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul
@@ -122,16 +122,17 @@
   try {
     dummy = mgr.explicit;
   } catch (ex) {
     is(ex.result, Cr.NS_ERROR_NOT_AVAILABLE, "mgr.explicit exception");
     haveExplicit = false;
   }
   let amounts = [
     "vsize",
+    "vsizeMaxContiguous",
     "resident",
     "residentFast",
     "heapAllocated",
     "heapOverheadRatio",
     "JSMainRuntimeGCHeap",
     "JSMainRuntimeTemporaryPeak",
     "JSMainRuntimeCompartmentsSystem",
     "JSMainRuntimeCompartmentsUser",
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -250,16 +250,24 @@
   "MEMORY_VSIZE": {
     "kind": "exponential",
     "low": "32 * 1024",
     "high": "16 * 1024 * 1024",
     "n_buckets": 100,
     "extended_statistics_ok": true,
     "description": "Virtual memory size (KB)"
   },
+  "MEMORY_VSIZE_MAX_CONTIGUOUS": {
+    "kind": "exponential",
+    "low": "32 * 1024",
+    "high": "16 * 1024 * 1024",
+    "n_buckets": 100,
+    "extended_statistics_ok": true,
+    "description": "Maximum-sized block of contiguous virtual memory (KB)"
+  },
   "MEMORY_JS_COMPARTMENTS_SYSTEM": {
     "kind": "exponential",
     "high": "1000",
     "n_buckets": 50,
     "extended_statistics_ok": true,
     "description": "Total JavaScript compartments used for add-ons and internals."
   },
   "MEMORY_JS_COMPARTMENTS_USER": {
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -446,16 +446,17 @@ TelemetryPing.prototype = {
       };
     }
     let b = (id, n) => h(id, Ci.nsIMemoryReporter.UNITS_BYTES, n);
     let c = (id, n) => h(id, Ci.nsIMemoryReporter.UNITS_COUNT, n);
     let cc= (id, n) => h(id, Ci.nsIMemoryReporter.UNITS_COUNT_CUMULATIVE, n);
     let p = (id, n) => h(id, Ci.nsIMemoryReporter.UNITS_PERCENTAGE, n);
 
     b("MEMORY_VSIZE", "vsize");
+    b("MEMORY_VSIZE_MAX_CONTIGUOUS", "vsizeMaxContiguous");
     b("MEMORY_RESIDENT", "residentFast");
     b("MEMORY_HEAP_ALLOCATED", "heapAllocated");
     p("MEMORY_HEAP_COMMITTED_UNUSED_RATIO", "heapOverheadRatio");
     b("MEMORY_JS_GC_HEAP", "JSMainRuntimeGCHeap");
     b("MEMORY_JS_MAIN_RUNTIME_TEMPORARY_PEAK", "JSMainRuntimeTemporaryPeak");
     c("MEMORY_JS_COMPARTMENTS_SYSTEM", "JSMainRuntimeCompartmentsSystem");
     c("MEMORY_JS_COMPARTMENTS_USER", "JSMainRuntimeCompartmentsUser");
     b("MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED", "imagesContentUsedUncompressed");
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -174,17 +174,17 @@ interface nsIMemoryReporter : nsISupport
    * Units.  See the |units| comment in nsIMemoryReporterCallback.
    */
   const int32_t UNITS_BYTES = 0;
   const int32_t UNITS_COUNT = 1;
   const int32_t UNITS_COUNT_CUMULATIVE = 2;
   const int32_t UNITS_PERCENTAGE = 3;
 };
 
-[scriptable, builtinclass, uuid(4db7040a-16f9-4249-879b-fe72729c7ef5)]
+[scriptable, builtinclass, uuid(b8fbab52-cdc0-424d-ab18-a5d9fc4b98c8)]
 interface nsIMemoryReporterManager : nsISupports
 {
   /*
    * Return an enumerator of nsIMemoryReporters that are currently registered.
    */
   nsISimpleEnumerator enumerateReporters();
 
   /*
@@ -231,16 +231,19 @@ interface nsIMemoryReporterManager : nsI
    * |explicit| (UNITS_BYTES)  The total size of explicit memory allocations,
    * both at the OS-level (eg. via mmap, VirtualAlloc) and at the heap level
    * (eg. via malloc, calloc, operator new).  It covers all heap allocations,
    * but will miss any OS-level ones not covered by memory reporters.
    *
    * |vsize| (UNITS_BYTES)  The virtual size, i.e. the amount of address space
    * taken up.
    *
+   * |vsizeMaxContiguous| (UNITS_BYTES)  The size of the largest contiguous
+   * block of virtual memory.
+   *
    * |resident| (UNITS_BYTES)  The resident size (a.k.a. RSS or physical memory
    * used).
    *
    * |residentFast| (UNITS_BYTES)  This is like |resident|, but on Mac OS
    * |resident| can purge pages, which is slow.  It also affects the result of
    * |residentFast|, and so |resident| and |residentFast| should not be used
    * together.
    *
@@ -271,16 +274,17 @@ interface nsIMemoryReporterManager : nsI
    *
    * |ghostWindows| (UNITS_COUNT)  The number of ghost windows.
    *
    * |pageFaultsHard| (UNITS_COUNT_CUMULATIVE)  The number of hard (a.k.a.
    * major) page faults that have occurred since the process started.
    */
   readonly attribute int64_t explicit;
   readonly attribute int64_t vsize;
+  readonly attribute int64_t vsizeMaxContiguous;
   readonly attribute int64_t resident;
   readonly attribute int64_t residentFast;
 
   readonly attribute int64_t heapAllocated;
   readonly attribute int64_t heapOverheadRatio;
 
   readonly attribute int64_t JSMainRuntimeGCHeap;
   readonly attribute int64_t JSMainRuntimeTemporaryPeak;
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -52,29 +52,32 @@ static nsresult GetProcSelfStatmField(in
             *aN = fields[aField] * getpagesize();
             return NS_OK;
         }
     }
     return NS_ERROR_FAILURE;
 }
 
 #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
-static nsresult GetVsize(int64_t* aN)
+static nsresult
+VsizeDistinguishedAmount(int64_t* aN)
 {
     return GetProcSelfStatmField(0, aN);
 }
 
-static nsresult GetResident(int64_t* aN)
+static nsresult
+ResidentDistinguishedAmount(int64_t* aN)
 {
     return GetProcSelfStatmField(1, aN);
 }
 
-static nsresult GetResidentFast(int64_t* aN)
+static nsresult
+ResidentFastDistinguishedAmount(int64_t* aN)
 {
-    return GetResident(aN);
+    return ResidentDistinguishedAmount(aN);
 }
 
 #define HAVE_RESIDENT_UNIQUE_REPORTER
 class ResidentUniqueReporter MOZ_FINAL : public MemoryUniReporter
 {
 public:
   ResidentUniqueReporter()
     : MemoryUniReporter("resident-unique", KIND_OTHER, UNITS_BYTES,
@@ -165,39 +168,42 @@ static nsresult GetKinfoProcSelf(KINFO_P
     size_t size = sizeof(KINFO_PROC);
     if (sysctl(mib, miblen, aProc, &size, nullptr, 0))
         return NS_ERROR_FAILURE;
 
     return NS_OK;
 }
 
 #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
-static nsresult GetVsize(int64_t* aN)
+static nsresult
+VsizeDistinguishedAmount(int64_t* aN)
 {
     KINFO_PROC proc;
     nsresult rv = GetKinfoProcSelf(&proc);
     if (NS_SUCCEEDED(rv))
         *aN = KP_SIZE(proc);
 
     return rv;
 }
 
-static nsresult GetResident(int64_t* aN)
+static nsresult
+ResidentDistinguishedAmount(int64_t* aN)
 {
     KINFO_PROC proc;
     nsresult rv = GetKinfoProcSelf(&proc);
     if (NS_SUCCEEDED(rv))
         *aN = KP_RSS(proc);
 
     return rv;
 }
 
-static nsresult GetResidentFast(int64_t* aN)
+static nsresult
+ResidentFastDistinguishedAmount(int64_t* aN)
 {
-    return GetResident(aN);
+    return ResidentDistinguishedAmount(aN);
 }
 
 #elif defined(SOLARIS)
 
 #include <procfs.h>
 #include <fcntl.h>
 #include <unistd.h>
 
@@ -238,41 +244,44 @@ static void XMappingIter(int64_t& vsize,
             }
             free(prmapp);
         }
         close(mapfd);
     }
 }
 
 #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
-static nsresult GetVsize(int64_t* aN)
+static nsresult
+VsizeDistinguishedAmount(int64_t* aN)
 {
     int64_t vsize, resident;
     XMappingIter(vsize, resident);
     if (vsize == -1) {
         return NS_ERROR_FAILURE;
     }
     *aN = vsize;
     return NS_OK;
 }
 
-static nsresult GetResident(int64_t* aN)
+static nsresult
+ResidentDistinguishedAmount(int64_t* aN)
 {
     int64_t vsize, resident;
     XMappingIter(vsize, resident);
     if (resident == -1) {
         return NS_ERROR_FAILURE;
     }
     *aN = resident;
     return NS_OK;
 }
 
-static nsresult GetResidentFast(int64_t* aN)
+static nsresult
+ResidentFastDistinguishedAmount(int64_t* aN)
 {
-    return GetResident(aN);
+    return ResidentDistinguishedAmount(aN);
 }
 
 #elif defined(XP_MACOSX)
 
 #include <mach/mach_init.h>
 #include <mach/task.h>
 
 static bool GetTaskBasicInfo(struct task_basic_info* aTi)
@@ -282,97 +291,147 @@ static bool GetTaskBasicInfo(struct task
                                  (task_info_t)aTi, &count);
     return kr == KERN_SUCCESS;
 }
 
 // The VSIZE figure on Mac includes huge amounts of shared memory and is always
 // absurdly high, eg. 2GB+ even at start-up.  But both 'top' and 'ps' report
 // it, so we might as well too.
 #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
-static nsresult GetVsize(int64_t* aN)
+static nsresult
+VsizeDistinguishedAmount(int64_t* aN)
 {
     task_basic_info ti;
     if (!GetTaskBasicInfo(&ti))
         return NS_ERROR_FAILURE;
 
     *aN = ti.virtual_size;
     return NS_OK;
 }
 
 // If we're using jemalloc on Mac, we need to instruct jemalloc to purge the
 // pages it has madvise(MADV_FREE)'d before we read our RSS in order to get
 // an accurate result.  The OS will take away MADV_FREE'd pages when there's
 // memory pressure, so ideally, they shouldn't count against our RSS.
 //
 // Purging these pages can take a long time for some users (see bug 789975),
 // so we provide the option to get the RSS without purging first.
-static nsresult GetResident(int64_t* aN, bool aDoPurge)
+static nsresult ResidentDistinguishedAmountHelper(int64_t* aN, bool aDoPurge)
 {
 #ifdef HAVE_JEMALLOC_STATS
     if (aDoPurge) {
       Telemetry::AutoTimer<Telemetry::MEMORY_FREE_PURGED_PAGES_MS> timer;
       jemalloc_purge_freed_pages();
     }
 #endif
 
     task_basic_info ti;
     if (!GetTaskBasicInfo(&ti))
         return NS_ERROR_FAILURE;
 
     *aN = ti.resident_size;
     return NS_OK;
 }
 
-static nsresult GetResidentFast(int64_t* aN)
+static nsresult
+ResidentFastDistinguishedAmount(int64_t* aN)
 {
-    return GetResident(aN, /* doPurge = */ false);
+    return ResidentDistinguishedAmountHelper(aN, /* doPurge = */ false);
 }
 
-static nsresult GetResident(int64_t* aN)
+static nsresult
+ResidentDistinguishedAmount(int64_t* aN)
 {
-    return GetResident(aN, /* doPurge = */ true);
+    return ResidentDistinguishedAmountHelper(aN, /* doPurge = */ true);
 }
 
 #elif defined(XP_WIN)
 
 #include <windows.h>
 #include <psapi.h>
+#include <algorithm>
 
 #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
-static nsresult GetVsize(int64_t* aN)
+static nsresult
+VsizeDistinguishedAmount(int64_t* aN)
 {
     MEMORYSTATUSEX s;
     s.dwLength = sizeof(s);
 
     if (!GlobalMemoryStatusEx(&s)) {
         return NS_ERROR_FAILURE;
     }
 
     *aN = s.ullTotalVirtual - s.ullAvailVirtual;
     return NS_OK;
 }
 
-static nsresult GetResident(int64_t* aN)
+static nsresult
+ResidentDistinguishedAmount(int64_t* aN)
 {
     PROCESS_MEMORY_COUNTERS pmc;
     pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
 
     if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
         return NS_ERROR_FAILURE;
     }
 
     *aN = pmc.WorkingSetSize;
     return NS_OK;
 }
 
-static nsresult GetResidentFast(int64_t* aN)
+static nsresult
+ResidentFastDistinguishedAmount(int64_t* aN)
+{
+    return ResidentDistinguishedAmount(aN);
+}
+
+#define HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER 1
+static nsresult
+VsizeMaxContiguousDistinguishedAmount(int64_t* aN)
 {
-    return GetResident(aN);
+    SIZE_T biggestRegion = 0;
+    MEMORY_BASIC_INFORMATION vmemInfo = {0};
+    for (size_t currentAddress = 0; ; ) {
+        if (!VirtualQuery((LPCVOID)currentAddress, &vmemInfo, sizeof(vmemInfo))) {
+            // Something went wrong, just return whatever we've got already.
+            break;
+        }
+
+        if (vmemInfo.State == MEM_FREE) {
+            biggestRegion = std::max(biggestRegion, vmemInfo.RegionSize);
+        }
+
+        SIZE_T lastAddress = currentAddress;
+        currentAddress += vmemInfo.RegionSize;
+
+        // If we overflow, we've examined all of the address space.
+        if (currentAddress < lastAddress) {
+            break;
+        }
+    }
+
+    *aN = biggestRegion;
+    return NS_OK;
 }
 
+class VsizeMaxContiguousReporter MOZ_FINAL : public MemoryUniReporter
+{
+public:
+    VsizeMaxContiguousReporter()
+      : MemoryUniReporter("vsize-max-contiguous", KIND_OTHER, UNITS_BYTES,
+"Size of the maximum contiguous block of available virtual memory.")
+    {}
+
+    NS_IMETHOD GetAmount(int64_t* aAmount)
+    {
+        return VsizeMaxContiguousDistinguishedAmount(aAmount);
+    }
+};
+
 #define HAVE_PRIVATE_REPORTER
 class PrivateReporter MOZ_FINAL : public MemoryUniReporter
 {
 public:
     PrivateReporter()
       : MemoryUniReporter("private", KIND_OTHER, UNITS_BYTES,
 "Memory that cannot be shared with other processes, including memory that is "
 "committed and marked MEM_PRIVATE, data that is not mapped, and executable "
@@ -407,33 +466,39 @@ public:
 "thread stacks, memory explicitly mapped by the process via mmap and similar "
 "operations, and memory shared with other processes. This is the vsize figure "
 "as reported by 'top' and 'ps'.  This figure is of limited use on Mac, where "
 "processes share huge amounts of memory with one another.  But even on other "
 "operating systems, 'resident' is a much better measure of the memory "
 "resources used by the process.")
     {}
 
-    NS_IMETHOD GetAmount(int64_t* aAmount) { return GetVsize(aAmount); }
+    NS_IMETHOD GetAmount(int64_t* aAmount)
+    {
+        return VsizeDistinguishedAmount(aAmount);
+    }
 };
 
 class ResidentReporter MOZ_FINAL : public MemoryUniReporter
 {
 public:
     ResidentReporter()
       : MemoryUniReporter("resident", KIND_OTHER, UNITS_BYTES,
 "Memory mapped by the process that is present in physical memory, also known "
 "as the resident set size (RSS).  This is the best single figure to use when "
 "considering the memory resources used by the process, but it depends both on "
 "other processes being run and details of the OS kernel and so is best used "
 "for comparing the memory usage of a single process at different points in "
 "time.")
     {}
 
-    NS_IMETHOD GetAmount(int64_t* aAmount) { return GetResident(aAmount); }
+    NS_IMETHOD GetAmount(int64_t* aAmount)
+    {
+        return ResidentDistinguishedAmount(aAmount);
+    }
 };
 #endif  // HAVE_VSIZE_AND_RESIDENT_REPORTERS
 
 #ifdef XP_UNIX
 
 #include <sys/resource.h>
 
 #define HAVE_PAGE_FAULT_REPORTERS 1
@@ -749,16 +814,20 @@ nsMemoryReporterManager::Init()
     RegisterReporter(new HeapOverheadRatioReporter);
 #endif
 
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
     RegisterReporter(new VsizeReporter);
     RegisterReporter(new ResidentReporter);
 #endif
 
+#ifdef HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER
+    RegisterReporter(new VsizeMaxContiguousReporter);
+#endif
+
 #ifdef HAVE_RESIDENT_UNIQUE_REPORTER
     RegisterReporter(new ResidentUniqueReporter);
 #endif
 
 #ifdef HAVE_PAGE_FAULT_REPORTERS
     RegisterReporter(new PageFaultsSoftReporter);
     RegisterReporter(new PageFaultsHardReporter);
 #endif
@@ -1036,39 +1105,50 @@ nsMemoryReporterManager::GetExplicit(int
     return NS_OK;
 #endif // HAVE_JEMALLOC_STATS
 }
 
 NS_IMETHODIMP
 nsMemoryReporterManager::GetVsize(int64_t* aVsize)
 {
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
-    return ::GetVsize(aVsize);
+    return VsizeDistinguishedAmount(aVsize);
 #else
     *aResident = 0;
     return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
 NS_IMETHODIMP
+nsMemoryReporterManager::GetVsizeMaxContiguous(int64_t* aAmount)
+{
+#ifdef HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER
+    return VsizeMaxContiguousDistinguishedAmount(aAmount);
+#else
+    *aAmount = 0;
+    return NS_ERROR_NOT_AVAILABLE;
+#endif
+}
+
+NS_IMETHODIMP
 nsMemoryReporterManager::GetResident(int64_t* aAmount)
 {
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
-    return ::GetResident(aAmount);
+    return ResidentDistinguishedAmount(aAmount);
 #else
     *aAmount = 0;
     return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
 NS_IMETHODIMP
 nsMemoryReporterManager::GetResidentFast(int64_t* aAmount)
 {
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
-    return ::GetResidentFast(aAmount);
+    return ResidentFastDistinguishedAmount(aAmount);
 #else
     *aAmount = 0;
     return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
 NS_IMETHODIMP
 nsMemoryReporterManager::GetHeapAllocated(int64_t* aAmount)