Bug 939137 - part 1 - add largestContiguousVMBlock attribute to nsIMemoryReporterManager; r=bsmedberg
authorNathan Froyd <froydnj@mozilla.com>
Fri, 15 Nov 2013 13:04:43 -0500
changeset 170454 b3995a14d96884e29e63d7bfee70b0c83e3eedfb
parent 170453 8785dac978829a88c67c069bb670c5f570441c19
child 170455 86cf2e690f904815b9e842d4ebdc8b2f766934ea
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs939137
milestone28.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 939137 - part 1 - add largestContiguousVMBlock attribute to nsIMemoryReporterManager; r=bsmedberg
xpcom/base/nsIMemoryReporter.idl
xpcom/base/nsMemoryReporterManager.cpp
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -180,17 +180,17 @@ interface nsIMemoryReporter : nsISupport
 };
 
 [scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)]
 interface nsIFinishReportingCallback : nsISupports
 {
   void callback(in nsISupports data);
 };
 
-[scriptable, builtinclass, uuid(a1292276-726b-4ef5-a017-5a455d6664dd)]
+[scriptable, builtinclass, uuid(2596fa26-495a-4827-a5f5-e34e7f4dd7b5)]
 interface nsIMemoryReporterManager : nsISupports
 {
   /*
    * Initialize.
    */
   void init();
 
   /*
@@ -295,16 +295,20 @@ interface nsIMemoryReporterManager : nsI
    * |lowMemoryEvents{Virtual,Physical}| (UNITS_COUNT_CUMULATIVE)  The number
    * of low-{virtual,physical}-memory events that have occurred since the
    * process started.
    *
    * |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.
+   *
+   * |largestContiguousVMBlock| (UNITS_BYTES)  The size of the largest
+   * contiguous block of virtual memory.  Only available on Windows; on all
+   * other platforms, reading this value returns 0.
    */
   readonly attribute int64_t explicit;
   readonly attribute int64_t vsize;
   readonly attribute int64_t resident;
   readonly attribute int64_t residentFast;
 
   readonly attribute int64_t heapAllocated;
   readonly attribute int64_t heapOverheadRatio;
@@ -320,16 +324,18 @@ interface nsIMemoryReporterManager : nsI
 
   readonly attribute int64_t lowMemoryEventsVirtual;
   readonly attribute int64_t lowMemoryEventsPhysical;
 
   readonly attribute int64_t ghostWindows;
 
   readonly attribute int64_t pageFaultsHard;
 
+  readonly attribute int64_t largestContiguousVMBlock;
+
   /*
    * This attribute indicates if moz_malloc_usable_size() works.
    */
   [infallible] readonly attribute boolean hasMozMallocUsableSize;
 
   /*
    * Run a series of GC/CC's in an attempt to minimize the application's memory
    * usage.  When we're finished, we invoke the given runnable if it's not
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -332,16 +332,17 @@ static nsresult GetResident(int64_t* aN)
 {
     return GetResident(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)
 {
     MEMORYSTATUSEX s;
     s.dwLength = sizeof(s);
 
     if (!GlobalMemoryStatusEx(&s)) {
@@ -365,16 +366,44 @@ static nsresult GetResident(int64_t* aN)
     return NS_OK;
 }
 
 static nsresult GetResidentFast(int64_t* aN)
 {
     return GetResident(aN);
 }
 
+#define HAVE_LARGEST_CONTIGUOUS_BLOCK_REPORTERS 1
+static nsresult LargestContiguousVMBlock(int64_t* 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;
+}
+
 #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 "
@@ -1378,16 +1407,27 @@ nsMemoryReporterManager::GetPageFaultsHa
     return PageFaultsHardDistinguishedAmount(aAmount);
 #else
     *aAmount = 0;
     return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
 NS_IMETHODIMP
+nsMemoryReporterManager::GetLargestContiguousVMBlock(int64_t* aAmount)
+{
+#ifdef HAVE_LARGEST_CONTIGUOUS_BLOCK_REPORTERS
+    return LargestContiguousVMBlock(aAmount);
+#else
+    *aAmount = 0;
+    return NS_ERROR_NOT_AVAILABLE;
+#endif
+}
+
+NS_IMETHODIMP
 nsMemoryReporterManager::GetHasMozMallocUsableSize(bool* aHas)
 {
     void* p = malloc(16);
     if (!p) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
     size_t usable = moz_malloc_usable_size(p);
     free(p);