Bug 731890 - Convert the 12 "images" memory reporters to a single multi-reporter. r=jlebar.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 01 Mar 2012 16:05:32 -0800
changeset 88320 fed586e905ec0a8712ca6b9f8127e5133e690b30
parent 88319 46a1c807df2b929348214f023d766b9ba951ea84
child 88321 9613e21afa3425f13a8ff343f3ea581f9d1c17dc
push id157
push userMs2ger@gmail.com
push dateWed, 07 Mar 2012 19:27:10 +0000
reviewersjlebar
bugs731890
milestone13.0a1
Bug 731890 - Convert the 12 "images" memory reporters to a single multi-reporter. r=jlebar.
image/src/imgLoader.cpp
toolkit/components/telemetry/TelemetryPing.js
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -132,192 +132,204 @@ static void PrintImageDecoders()
         printf("Have decoder for mime type: %s\n", xcs.get()+decoderContract.Length());
       }
     }
   }
 }
 #endif
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ImagesMallocSizeOf, "images")
- 
+
 class imgMemoryReporter MOZ_FINAL :
-  public nsIMemoryReporter
+  public nsIMemoryMultiReporter
 {
 public:
-  enum ReporterType {
-    CHROME_BIT = PR_BIT(0),
-    USED_BIT   = PR_BIT(1),
-    RAW_BIT    = PR_BIT(2),
-    HEAP_BIT   = PR_BIT(3),
-
-    ChromeUsedRaw                     = CHROME_BIT | USED_BIT | RAW_BIT | HEAP_BIT,
-    ChromeUsedUncompressedHeap        = CHROME_BIT | USED_BIT | HEAP_BIT,
-    ChromeUsedUncompressedNonheap     = CHROME_BIT | USED_BIT,
-    ChromeUnusedRaw                   = CHROME_BIT | RAW_BIT | HEAP_BIT,
-    ChromeUnusedUncompressedHeap      = CHROME_BIT | HEAP_BIT,
-    ChromeUnusedUncompressedNonheap   = CHROME_BIT,
-    ContentUsedRaw                    = USED_BIT | RAW_BIT | HEAP_BIT,
-    ContentUsedUncompressedHeap       = USED_BIT | HEAP_BIT,
-    ContentUsedUncompressedNonheap    = USED_BIT,
-    ContentUnusedRaw                  = RAW_BIT | HEAP_BIT,
-    ContentUnusedUncompressedHeap     = HEAP_BIT,
-    ContentUnusedUncompressedNonheap  = 0
-  };
-
-  imgMemoryReporter(ReporterType aType)
-    : mType(aType)
+  imgMemoryReporter()
   {
-    // If the RAW bit is set, HEAP should also be set, because we don't
-    // currently understand storing compressed image data off the heap.
-    NS_ASSERTION(!(aType & RAW_BIT) || (aType & HEAP_BIT),
-                 "RAW bit should imply HEAP bit.");
   }
 
   NS_DECL_ISUPPORTS
 
-  NS_IMETHOD GetProcess(nsACString &process)
-  {
-    process.Truncate();
-    return NS_OK;
-  }
-
-  NS_IMETHOD GetPath(nsACString &path)
+  NS_IMETHOD GetName(nsACString &name)
   {
-    if (mType == ChromeUsedRaw) {
-      path.AssignLiteral("explicit/images/chrome/used/raw");
-    } else if (mType == ChromeUsedUncompressedHeap) {
-      path.AssignLiteral("explicit/images/chrome/used/uncompressed-heap");
-    } else if (mType == ChromeUsedUncompressedNonheap) {
-      path.AssignLiteral("explicit/images/chrome/used/uncompressed-nonheap");
-    } else if (mType == ChromeUnusedRaw) {
-      path.AssignLiteral("explicit/images/chrome/unused/raw");
-    } else if (mType == ChromeUnusedUncompressedHeap) {
-      path.AssignLiteral("explicit/images/chrome/unused/uncompressed-heap");
-    } else if (mType == ChromeUnusedUncompressedNonheap) {
-      path.AssignLiteral("explicit/images/chrome/unused/uncompressed-nonheap");
-    } else if (mType == ContentUsedRaw) {
-      path.AssignLiteral("explicit/images/content/used/raw");
-    } else if (mType == ContentUsedUncompressedHeap) {
-      path.AssignLiteral("explicit/images/content/used/uncompressed-heap");
-    } else if (mType == ContentUsedUncompressedNonheap) {
-      path.AssignLiteral("explicit/images/content/used/uncompressed-nonheap");
-    } else if (mType == ContentUnusedRaw) {
-      path.AssignLiteral("explicit/images/content/unused/raw");
-    } else if (mType == ContentUnusedUncompressedHeap) {
-      path.AssignLiteral("explicit/images/content/unused/uncompressed-heap");
-    } else if (mType == ContentUnusedUncompressedNonheap) {
-      path.AssignLiteral("explicit/images/content/unused/uncompressed-nonheap");
-    }
+    name.Assign("images");
     return NS_OK;
   }
 
-  NS_IMETHOD GetKind(PRInt32 *kind)
+  NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
+                            nsISupports *closure)
   {
-    if (mType & HEAP_BIT) {
-      *kind = KIND_HEAP;
-    }
-    else {
-      *kind = KIND_MAPPED;
-    }
-    return NS_OK;
-  }
+    AllSizes chrome;
+    AllSizes content;
+    imgLoader::sChromeCache.EnumerateRead(EntryAllSizes, &chrome);
+    imgLoader::sCache.EnumerateRead(EntryAllSizes, &content);
+
+#define REPORT(_path, _kind, _amount, _desc)                                  \
+    do {                                                                      \
+      nsresult rv;                                                            \
+      rv = callback->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),      \
+                              _kind, nsIMemoryReporter::UNITS_BYTES, _amount, \
+                              NS_LITERAL_CSTRING(_desc), closure);            \
+      NS_ENSURE_SUCCESS(rv, rv);                                              \
+    } while (0)
+
+    REPORT("explicit/images/chrome/used/raw",
+           nsIMemoryReporter::KIND_HEAP, chrome.mUsedRaw,
+           "Memory used by in-use chrome images (compressed data).");
+
+    REPORT("explicit/images/chrome/used/uncompressed-heap",
+           nsIMemoryReporter::KIND_HEAP, chrome.mUsedUncompressedHeap,
+           "Memory used by in-use chrome images (uncompressed data).");
+
+    REPORT("explicit/images/chrome/used/uncompressed-nonheap",
+           nsIMemoryReporter::KIND_NONHEAP, chrome.mUsedUncompressedNonheap,
+           "Memory used by in-use chrome images (uncompressed data).");
+
+    REPORT("explicit/images/chrome/unused/raw",
+           nsIMemoryReporter::KIND_HEAP, chrome.mUnusedRaw,
+           "Memory used by not in-use chrome images (compressed data).");
 
-  NS_IMETHOD GetUnits(PRInt32 *units)
-  {
-    *units = UNITS_BYTES;
+    REPORT("explicit/images/chrome/unused/uncompressed-heap",
+           nsIMemoryReporter::KIND_HEAP, chrome.mUnusedUncompressedHeap,
+           "Memory used by not in-use chrome images (uncompressed data).");
+
+    REPORT("explicit/images/chrome/unused/uncompressed-nonheap",
+           nsIMemoryReporter::KIND_NONHEAP, chrome.mUnusedUncompressedNonheap,
+           "Memory used by not in-use chrome images (uncompressed data).");
+
+    REPORT("explicit/images/content/used/raw",
+           nsIMemoryReporter::KIND_HEAP, content.mUsedRaw,
+           "Memory used by in-use content images (compressed data).");
+
+    REPORT("explicit/images/content/used/uncompressed-heap",
+           nsIMemoryReporter::KIND_HEAP, content.mUsedUncompressedHeap,
+           "Memory used by in-use content images (uncompressed data).");
+
+    REPORT("explicit/images/content/used/uncompressed-nonheap",
+           nsIMemoryReporter::KIND_NONHEAP, content.mUsedUncompressedNonheap,
+           "Memory used by in-use content images (uncompressed data).");
+
+    REPORT("explicit/images/content/unused/raw",
+           nsIMemoryReporter::KIND_HEAP, content.mUnusedRaw,
+           "Memory used by not in-use content images (compressed data).");
+
+    REPORT("explicit/images/content/unused/uncompressed-heap",
+           nsIMemoryReporter::KIND_HEAP, content.mUnusedUncompressedHeap,
+           "Memory used by not in-use content images (uncompressed data).");
+
+    REPORT("explicit/images/content/unused/uncompressed-nonheap",
+           nsIMemoryReporter::KIND_NONHEAP, content.mUnusedUncompressedNonheap,
+           "Memory used by not in-use content images (uncompressed data).");
+
+#undef REPORT
+
     return NS_OK;
   }
 
-  struct EnumArg {
-    EnumArg(ReporterType aType)
-      : rtype(aType), n(0)
-    { }
+  NS_IMETHOD GetExplicitNonHeap(PRInt64 *n)
+  {
+    size_t n2 = 0;
+    imgLoader::sChromeCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
+    imgLoader::sCache.EnumerateRead(EntryExplicitNonHeapSize, &n2);
+    *n = n2;
+    return NS_OK;
+  }
 
-    ReporterType rtype;
-    size_t n;
+  static PRInt64 GetImagesContentUsedUncompressed()
+  {
+    size_t n = 0;
+    imgLoader::sCache.EnumerateRead(EntryUsedUncompressedSize, &n);
+    return n;
+  }
+
+private:
+  struct AllSizes {
+    size_t mUsedRaw;
+    size_t mUsedUncompressedHeap;
+    size_t mUsedUncompressedNonheap;
+    size_t mUnusedRaw;
+    size_t mUnusedUncompressedHeap;
+    size_t mUnusedUncompressedNonheap;
+
+    AllSizes() {
+      memset(this, 0, sizeof(*this));
+    }
   };
 
-  static PLDHashOperator EnumEntries(const nsACString&,
-                                     imgCacheEntry *entry,
-                                     void *userArg)
+  static PLDHashOperator EntryAllSizes(const nsACString&,
+                                       imgCacheEntry *entry,
+                                       void *userArg)
   {
-    EnumArg *arg = static_cast<EnumArg*>(userArg);
-    ReporterType rtype = arg->rtype;
-
-    if (rtype & USED_BIT) {
-      if (entry->HasNoProxies())
-        return PL_DHASH_NEXT;
-    } else {
-      if (!entry->HasNoProxies())
-        return PL_DHASH_NEXT;
-    }
-
     nsRefPtr<imgRequest> req = entry->GetRequest();
     Image *image = static_cast<Image*>(req->mImage.get());
-    if (!image)
-      return PL_DHASH_NEXT;
-
-    if (rtype & RAW_BIT) {
-      arg->n += image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf);
-    } else if (rtype & HEAP_BIT) {
-      arg->n += image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
-    } else {
-      arg->n += image->NonHeapSizeOfDecoded();
+    if (image) {
+      AllSizes *sizes = static_cast<AllSizes*>(userArg);
+      if (entry->HasNoProxies()) {
+        sizes->mUnusedRaw +=
+          image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf);
+        sizes->mUnusedUncompressedHeap +=
+          image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
+        sizes->mUnusedUncompressedNonheap += image->NonHeapSizeOfDecoded();
+      } else {
+        sizes->mUsedRaw +=
+          image->HeapSizeOfSourceWithComputedFallback(ImagesMallocSizeOf);
+        sizes->mUsedUncompressedHeap +=
+          image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
+        sizes->mUsedUncompressedNonheap += image->NonHeapSizeOfDecoded();
+      }
     }
 
     return PL_DHASH_NEXT;
   }
 
-  NS_IMETHOD GetAmount(PRInt64 *amount)
+  static PLDHashOperator EntryExplicitNonHeapSize(const nsACString&,
+                                                  imgCacheEntry *entry,
+                                                  void *userArg)
   {
-    EnumArg arg(mType);
-    if (mType & CHROME_BIT) {
-      imgLoader::sChromeCache.EnumerateRead(EnumEntries, &arg);
-    } else {
-      imgLoader::sCache.EnumerateRead(EnumEntries, &arg);
+    size_t *n = static_cast<size_t*>(userArg);
+    nsRefPtr<imgRequest> req = entry->GetRequest();
+    Image *image = static_cast<Image*>(req->mImage.get());
+    if (image) {
+      *n += image->NonHeapSizeOfDecoded();
     }
 
-    *amount = arg.n;
-    return NS_OK;
+    return PL_DHASH_NEXT;
   }
 
-  NS_IMETHOD GetDescription(nsACString &desc)
+  static PLDHashOperator EntryUsedUncompressedSize(const nsACString&,
+                                                   imgCacheEntry *entry,
+                                                   void *userArg)
   {
-    if (mType == ChromeUsedRaw) {
-      desc.AssignLiteral("Memory used by in-use chrome images (compressed data).");
-    } else if (mType == ChromeUsedUncompressedHeap) {
-      desc.AssignLiteral("Memory used by in-use chrome images (uncompressed data).");
-    } else if (mType == ChromeUsedUncompressedNonheap) {
-      desc.AssignLiteral("Memory used by in-use chrome images (uncompressed data).");
-    } else if (mType == ChromeUnusedRaw) {
-      desc.AssignLiteral("Memory used by not in-use chrome images (compressed data).");
-    } else if (mType == ChromeUnusedUncompressedHeap) {
-      desc.AssignLiteral("Memory used by not in-use chrome images (uncompressed data).");
-    } else if (mType == ChromeUnusedUncompressedNonheap) {
-      desc.AssignLiteral("Memory used by not in-use chrome images (uncompressed data).");
-    } else if (mType == ContentUsedRaw) {
-      desc.AssignLiteral("Memory used by in-use content images (compressed data).");
-    } else if (mType == ContentUsedUncompressedHeap) {
-      desc.AssignLiteral("Memory used by in-use content images (uncompressed data).");
-    } else if (mType == ContentUsedUncompressedNonheap) {
-      desc.AssignLiteral("Memory used by in-use content images (uncompressed data).");
-    } else if (mType == ContentUnusedRaw) {
-      desc.AssignLiteral("Memory used by not in-use content images (compressed data).");
-    } else if (mType == ContentUnusedUncompressedHeap) {
-      desc.AssignLiteral("Memory used by not in-use content images (uncompressed data).");
-    } else if (mType == ContentUnusedUncompressedNonheap) {
-      desc.AssignLiteral("Memory used by not in-use content images (uncompressed data).");
+    if (!entry->HasNoProxies()) {
+      size_t *n = static_cast<size_t*>(userArg);
+      nsRefPtr<imgRequest> req = entry->GetRequest();
+      Image *image = static_cast<Image*>(req->mImage.get());
+      if (image) {
+        *n += image->HeapSizeOfDecodedWithComputedFallback(ImagesMallocSizeOf);
+        *n += image->NonHeapSizeOfDecoded();
+      }
     }
-    return NS_OK;
+
+    return PL_DHASH_NEXT;
   }
-
-  ReporterType mType;
 };
 
-NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryReporter)
+// This is used by telemetry.
+NS_MEMORY_REPORTER_IMPLEMENT(
+  ImagesContentUsedUncompressed,
+  "images-content-used-uncompressed",
+  KIND_OTHER,
+  UNITS_BYTES,
+  imgMemoryReporter::GetImagesContentUsedUncompressed,
+  "This is the sum of the 'explicit/images/content/used/uncompressed-heap' "
+  "and 'explicit/images/content/used/uncompressed-nonheap' numbers.  However, "
+  "it is measured at a different time and so may give slightly different "
+  "results.")
+
+NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryMultiReporter)
 
 NS_IMPL_ISUPPORTS3(nsProgressNotificationProxy,
                      nsIProgressEventSink,
                      nsIChannelEventSink,
                      nsIInterfaceRequestor)
 
 NS_IMETHODIMP
 nsProgressNotificationProxy::OnProgress(nsIRequest* request,
@@ -917,28 +929,18 @@ nsresult imgLoader::InitCache()
 
   PRInt32 cachesize;
   rv = Preferences::GetInt("image.cache.size", &cachesize);
   if (NS_SUCCEEDED(rv))
     sCacheMaxSize = cachesize;
   else
     sCacheMaxSize = 5 * 1024 * 1024;
 
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUsedRaw));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUsedUncompressedHeap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUsedUncompressedNonheap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUnusedRaw));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUnusedUncompressedHeap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ChromeUnusedUncompressedNonheap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUsedRaw));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUsedUncompressedHeap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUsedUncompressedNonheap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUnusedRaw));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUnusedUncompressedHeap));
-  NS_RegisterMemoryReporter(new imgMemoryReporter(imgMemoryReporter::ContentUnusedUncompressedNonheap));
+  NS_RegisterMemoryMultiReporter(new imgMemoryReporter());
+  NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ImagesContentUsedUncompressed));
   
   return NS_OK;
 }
 
 nsresult imgLoader::Init()
 {
   ReadAcceptHeaderPref();
 
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -57,17 +57,17 @@ const TELEMETRY_DELAY = 60000;
 // about:memory values to turn into histograms
 const MEM_HISTOGRAMS = {
   "js-gc-heap": "MEMORY_JS_GC_HEAP",
   "js-compartments-system": "MEMORY_JS_COMPARTMENTS_SYSTEM",
   "js-compartments-user": "MEMORY_JS_COMPARTMENTS_USER",
   "explicit": "MEMORY_EXPLICIT",
   "resident": "MEMORY_RESIDENT",
   "storage-sqlite": "MEMORY_STORAGE_SQLITE",
-  "explicit/images/content/used/uncompressed":
+  "images-content-used-uncompressed":
     "MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED",
   "heap-allocated": "MEMORY_HEAP_ALLOCATED",
   "page-faults-hard": "PAGE_FAULTS_HARD",
   "low-memory-events-virtual": "LOW_MEMORY_EVENTS_VIRTUAL",
   "low-memory-events-physical": "LOW_MEMORY_EVENTS_PHYSICAL"
 };
 // Seconds of idle time before pinging.
 // On idle-daily a gather-telemetry notification is fired, during it probes can