Bug 1042305 - Increase ImageCache size and add MemoryPressure support r=gw280
authorSotaro Ikeda <sikeda@mozilla.com>
Mon, 25 Aug 2014 12:01:46 -0700
changeset 223087 db8e5ad4a738d77ae7e87c6191296031db396f59
parent 223086 8bf7fb1836c14abbaf823ad1b82c4f12a8e3eda1
child 223088 fee5a931a563027809c7fafdc8cb987a014e316c
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw280
bugs1042305
milestone34.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 1042305 - Increase ImageCache size and add MemoryPressure support r=gw280
b2g/app/b2g.js
dom/canvas/CanvasImageCache.cpp
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -49,17 +49,17 @@ pref("browser.cache.disk.smart_size.firs
 pref("browser.cache.memory.enable", true);
 pref("browser.cache.memory.capacity", 1024); // kilobytes
 
 pref("browser.cache.memory_limit", 2048); // 2 MB
 
 /* image cache prefs */
 pref("image.cache.size", 1048576); // bytes
 pref("image.high_quality_downscaling.enabled", false);
-pref("canvas.image.cache.limit", 10485760); // 10 MB
+pref("canvas.image.cache.limit", 20971520); // 20 MB
 
 /* offline cache prefs */
 pref("browser.offline-apps.notify", false);
 pref("browser.cache.offline.enable", true);
 pref("offline-apps.allow_by_default", true);
 
 /* protocol warning prefs */
 pref("network.protocol-handler.warn-external.tel", false);
--- a/dom/canvas/CanvasImageCache.cpp
+++ b/dom/canvas/CanvasImageCache.cpp
@@ -80,55 +80,130 @@ public:
   enum { ALLOW_MEMMOVE = true };
 
   nsAutoPtr<ImageCacheEntryData> mData;
 };
 
 static bool sPrefsInitialized = false;
 static int32_t sCanvasImageCacheLimit = 0;
 
+class ImageCacheObserver;
+
 class ImageCache MOZ_FINAL : public nsExpirationTracker<ImageCacheEntryData,4> {
 public:
   // We use 3 generations of 1 second each to get a 2-3 seconds timeout.
   enum { GENERATION_MS = 1000 };
-  ImageCache()
-    : nsExpirationTracker<ImageCacheEntryData,4>(GENERATION_MS)
-    , mTotal(0)
-  {
-    if (!sPrefsInitialized) {
-      sPrefsInitialized = true;
-      Preferences::AddIntVarCache(&sCanvasImageCacheLimit, "canvas.image.cache.limit", 0);
-    }
-  }
-  ~ImageCache() {
-    AgeAllGenerations();
-  }
+  ImageCache();
+  ~ImageCache();
 
   virtual void NotifyExpired(ImageCacheEntryData* aObject)
   {
     mTotal -= aObject->SizeInBytes();
     RemoveObject(aObject);
     // Deleting the entry will delete aObject since the entry owns aObject
     mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas));
   }
 
   nsTHashtable<ImageCacheEntry> mCache;
   size_t mTotal;
+  nsRefPtr<ImageCacheObserver> mImageCacheObserver;
 };
 
 static ImageCache* gImageCache = nullptr;
 
+// Listen memory-pressure event for image cache purge
+class ImageCacheObserver MOZ_FINAL : public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  ImageCacheObserver(ImageCache* aImageCache)
+    : mImageCache(aImageCache)
+  {
+    RegisterMemoryPressureEvent();
+  }
+
+  void Destroy()
+  {
+    UnregisterMemoryPressureEvent();
+    mImageCache = nullptr;
+  }
+
+  NS_IMETHODIMP Observe(nsISupports* aSubject,
+                        const char* aTopic,
+                        const char16_t* aSomeData)
+  {
+    if (!mImageCache || strcmp(aTopic, "memory-pressure")) {
+      return NS_OK;
+    }
+
+    mImageCache->AgeAllGenerations();
+    return NS_OK;
+  }
+
+private:
+  virtual ~ImageCacheObserver()
+  {
+  }
+
+  void RegisterMemoryPressureEvent()
+  {
+    nsCOMPtr<nsIObserverService> observerService =
+      mozilla::services::GetObserverService();
+
+    MOZ_ASSERT(observerService);
+
+    if (observerService) {
+      observerService->AddObserver(this, "memory-pressure", false);
+    }
+  }
+
+  void UnregisterMemoryPressureEvent()
+  {
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+
+    // Do not assert on observerService here. This might be triggered by
+    // the cycle collector at a late enough time, that XPCOM services are
+    // no longer available. See bug 1029504.
+    if (observerService) {
+        observerService->RemoveObserver(this, "memory-pressure");
+    }
+  }
+
+  ImageCache* mImageCache;
+};
+
+NS_IMPL_ISUPPORTS(ImageCacheObserver, nsIObserver)
+
 class CanvasImageCacheShutdownObserver MOZ_FINAL : public nsIObserver
 {
   ~CanvasImageCacheShutdownObserver() {}
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 };
 
+ImageCache::ImageCache()
+  : nsExpirationTracker<ImageCacheEntryData,4>(GENERATION_MS)
+  , mTotal(0)
+{
+  if (!sPrefsInitialized) {
+    sPrefsInitialized = true;
+    Preferences::AddIntVarCache(&sCanvasImageCacheLimit, "canvas.image.cache.limit", 0);
+  }
+  mImageCacheObserver = new ImageCacheObserver(this);
+  MOZ_RELEASE_ASSERT(mImageCacheObserver, "Can't alloc ImageCacheObserver");
+}
+
+ImageCache::~ImageCache() {
+  AgeAllGenerations();
+  mImageCacheObserver->Destroy();
+}
+
 void
 CanvasImageCache::NotifyDrawImage(Element* aImage,
                                   HTMLCanvasElement* aCanvas,
                                   imgIRequest* aRequest,
                                   SourceSurface* aSource,
                                   const gfxIntSize& aSize)
 {
   if (!gImageCache) {