Bug 1212833 - Delay the MemoryPressure when an application goes to background. r=gsvelto
authorVivien Nicolas <vnicolas@mozilla.com>
Wed, 04 Nov 2015 04:26:00 +0100
changeset 306851 0f15d62411bfabd985586bb7e75d33702af0a7a3
parent 306850 0fcb7abf3523a32868dc0b66b5ef02432a304801
child 306852 826b011c1a7cfa480e8d7f74564af6f0e459228d
push id7204
push usercku@mozilla.com
push dateThu, 05 Nov 2015 15:38:26 +0000
reviewersgsvelto
bugs1212833
milestone45.0a1
Bug 1212833 - Delay the MemoryPressure when an application goes to background. r=gsvelto
b2g/app/b2g.js
dom/ipc/ProcessPriorityManager.cpp
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -688,16 +688,17 @@ pref("layout.css.scroll-snap.enabled", t
 
 // Enable the ProcessPriorityManager, and give processes with no visible
 // documents a 1s grace period before they're eligible to be marked as
 // background. Background processes that are perceivable due to playing
 // media are given a longer grace period to accomodate changing tracks, etc.
 pref("dom.ipc.processPriorityManager.enabled", true);
 pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000);
 pref("dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS", 5000);
+pref("dom.ipc.processPriorityManager.memoryPressureGracePeriodMS", 3000);
 pref("dom.ipc.processPriorityManager.temporaryPriorityLockMS", 5000);
 
 // Number of different background/foreground levels for background/foreground
 // processes.  We use these different levels to force the low-memory killer to
 // kill processes in a LRU order.
 pref("dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels", 5);
 pref("dom.ipc.processPriorityManager.BACKGROUND_PERCEIVABLE.LRUPoolLevels", 4);
 
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -341,16 +341,17 @@ public:
   void Freeze();
   void Unfreeze();
 
   void ShutDown();
 
 private:
   static uint32_t sBackgroundPerceivableGracePeriodMS;
   static uint32_t sBackgroundGracePeriodMS;
+  static uint32_t sMemoryPressureGracePeriodMS;
 
   void FireTestOnlyObserverNotification(
     const char* aTopic,
     const nsACString& aData = EmptyCString());
 
   void FireTestOnlyObserverNotification(
     const char* aTopic,
     const char* aData = nullptr);
@@ -365,28 +366,30 @@ private:
   bool mFrozen;
 
   /**
    * Used to implement NameWithComma().
    */
   nsAutoCString mNameWithComma;
 
   nsCOMPtr<nsITimer> mResetPriorityTimer;
+  nsCOMPtr<nsITimer> mMemoryPressureTimer;
 };
 
 /* static */ bool ProcessPriorityManagerImpl::sInitialized = false;
 /* static */ bool ProcessPriorityManagerImpl::sPrefsEnabled = false;
 /* static */ bool ProcessPriorityManagerImpl::sRemoteTabsDisabled = true;
 /* static */ bool ProcessPriorityManagerImpl::sTestMode = false;
 /* static */ bool ProcessPriorityManagerImpl::sPrefListenersRegistered = false;
 /* static */ bool ProcessPriorityManagerImpl::sFrozen = false;
 /* static */ StaticRefPtr<ProcessPriorityManagerImpl>
   ProcessPriorityManagerImpl::sSingleton;
 /* static */ uint32_t ParticularProcessPriorityManager::sBackgroundPerceivableGracePeriodMS = 0;
 /* static */ uint32_t ParticularProcessPriorityManager::sBackgroundGracePeriodMS = 0;
+/* static */ uint32_t ParticularProcessPriorityManager::sMemoryPressureGracePeriodMS = 0;
 
 NS_IMPL_ISUPPORTS(ProcessPriorityManagerImpl,
                   nsIObserver,
                   nsISupportsWeakReference);
 
 /* static */ void
 ProcessPriorityManagerImpl::PrefChangedCallback(const char* aPref,
                                                 void* aClosure)
@@ -696,16 +699,18 @@ ParticularProcessPriorityManager::Partic
 
 void
 ParticularProcessPriorityManager::StaticInit()
 {
   Preferences::AddUintVarCache(&sBackgroundPerceivableGracePeriodMS,
                                "dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS");
   Preferences::AddUintVarCache(&sBackgroundGracePeriodMS,
                                "dom.ipc.processPriorityManager.backgroundGracePeriodMS");
+  Preferences::AddUintVarCache(&sMemoryPressureGracePeriodMS,
+                               "dom.ipc.processPriorityManager.memoryPressureGracePeriodMS");
 }
 
 void
 ParticularProcessPriorityManager::Init()
 {
   RegisterWakeLockObserver(this);
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
@@ -1009,20 +1014,31 @@ ParticularProcessPriorityManager::Schedu
   LOGP("Scheduling reset timer to fire in %dms.", timeout);
   mResetPriorityTimer = do_CreateInstance("@mozilla.org/timer;1");
   mResetPriorityTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
 }
 
 NS_IMETHODIMP
 ParticularProcessPriorityManager::Notify(nsITimer* aTimer)
 {
-  LOGP("Reset priority timer callback; about to ResetPriorityNow.");
-  ResetPriorityNow();
-  mResetPriorityTimer = nullptr;
-  return NS_OK;
+  if (mResetPriorityTimer == aTimer) {
+    LOGP("Reset priority timer callback; about to ResetPriorityNow.");
+    ResetPriorityNow();
+    mResetPriorityTimer = nullptr;
+    return NS_OK;
+  }
+
+  if (mContentParent && mMemoryPressureTimer == aTimer) {
+    Unused << mContentParent->SendFlushMemory(NS_LITERAL_STRING("lowering-priority"));
+    mMemoryPressureTimer = nullptr;
+    return NS_OK;
+  }
+
+  NS_WARNING("Unexpected timer!");
+  return NS_ERROR_INVALID_POINTER;
 }
 
 bool
 ParticularProcessPriorityManager::HasAppType(const char* aAppType)
 {
   const ManagedContainer<PBrowserParent>& browsers =
     mContentParent->ManagedPBrowserParent();
   for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
@@ -1137,20 +1153,28 @@ ParticularProcessPriorityManager::SetPri
   mPriority = aPriority;
   hal::SetProcessPriority(Pid(), mPriority);
 
   if (oldPriority != mPriority) {
     ProcessPriorityManagerImpl::GetSingleton()->
       NotifyProcessPriorityChanged(this, oldPriority);
 
     Unused << mContentParent->SendNotifyProcessPriorityChanged(mPriority);
-  }
+
+    if (mMemoryPressureTimer) {
+      mMemoryPressureTimer->Cancel();
+      mMemoryPressureTimer = nullptr;
+    }
 
-  if (aPriority < PROCESS_PRIORITY_FOREGROUND) {
-    Unused << mContentParent->SendFlushMemory(NS_LITERAL_STRING("lowering-priority"));
+    if (aPriority < PROCESS_PRIORITY_FOREGROUND) {
+      mMemoryPressureTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+      mMemoryPressureTimer->InitWithCallback(this,
+                                             sMemoryPressureGracePeriodMS,
+                                             nsITimer::TYPE_ONE_SHOT);
+    }
   }
 
   FireTestOnlyObserverNotification("process-priority-set",
     ProcessPriorityToString(mPriority));
 }
 
 void
 ParticularProcessPriorityManager::Freeze()