Bug 1385238 - Reset execution budget when background state changes. r=bkelly
authorAndreas Farre <farre@mozilla.com>
Fri, 28 Jul 2017 09:31:00 -0400
changeset 422838 270ed5e9ce20133d88d0129df412d112c35a6a04
parent 422837 7ec849c7dae9826d0ec49bcb4df080be55a8c2f9
child 422839 63182061f15b06933aa6755d47c67ef700671355
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbkelly
bugs1385238
milestone56.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 1385238 - Reset execution budget when background state changes. r=bkelly
dom/base/TimeoutManager.cpp
dom/base/TimeoutManager.h
--- a/dom/base/TimeoutManager.cpp
+++ b/dom/base/TimeoutManager.cpp
@@ -200,17 +200,18 @@ TimeoutManager::MinSchedulingDelay() con
   // mExecutionBudget is -15ms
   // factor is 0.01, which is 1 ms/100ms
   // delay is 1000ms
   // then we will compute the minimum delay:
   // max(1000, - (- 15) * 1/0.01) = max(1000, 1500) = 1500
   TimeDuration unthrottled =
     isBackground ? TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)
                  : TimeDuration();
-  if (BudgetThrottlingEnabled() && mExecutionBudget < TimeDuration()) {
+  if (BudgetThrottlingEnabled(isBackground) &&
+      mExecutionBudget < TimeDuration()) {
     // Only throttle if execution budget is less than 0
     double factor = 1.0 / GetRegenerationFactor(mWindow.IsBackgroundInternal());
     return TimeDuration::Min(
       TimeDuration::FromMilliseconds(gBudgetThrottlingMaxDelay),
       TimeDuration::Max(unthrottled, -mExecutionBudget.MultDouble(factor)));
   }
   //
   return unthrottled;
@@ -327,18 +328,18 @@ TimeoutManager::UpdateBudget(const TimeS
 
   // The budget is adjusted by increasing it with the time since the
   // last budget update factored with the regeneration rate. If a
   // runnable has executed, subtract that duration from the
   // budget. The budget updated without consideration of wether the
   // window is active or not. If throttling is enabled and the window
   // is active and then becomes inactive, an overdrawn budget will
   // still be counted against the minimum delay.
-  if (BudgetThrottlingEnabled()) {
-    bool isBackground = mWindow.IsBackgroundInternal();
+  bool isBackground = mWindow.IsBackgroundInternal();
+  if (BudgetThrottlingEnabled(isBackground)) {
     double factor = GetRegenerationFactor(isBackground);
     TimeDuration regenerated = (aNow - mLastBudgetUpdate).MultDouble(factor);
     // Clamp the budget to the maximum allowed budget.
     mExecutionBudget = TimeDuration::Min(
       GetMaxBudget(isBackground), mExecutionBudget - aDuration + regenerated);
   }
   mLastBudgetUpdate = aNow;
 }
@@ -1138,16 +1139,18 @@ TimeoutManager::Thaw()
     aTimeout->SetWhenOrTimeRemaining(now, aTimeout->TimeRemaining());
     MOZ_DIAGNOSTIC_ASSERT(!aTimeout->When().IsNull());
   });
 }
 
 void
 TimeoutManager::UpdateBackgroundState()
 {
+  mExecutionBudget = GetMaxBudget(mWindow.IsBackgroundInternal());
+
   // When the window moves to the background or foreground we should
   // reschedule the TimeoutExecutor in case the MinSchedulingDelay()
   // changed.  Only do this if the window is not suspended and we
   // actually have a timeout.
   if (!mWindow.IsSuspended()) {
     OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts);
     Timeout* nextTimeout = iter.Next();
     if (nextTimeout) {
@@ -1203,28 +1206,32 @@ ThrottleTimeoutsCallback::Notify(nsITime
   mWindow->AsInner()->TimeoutManager().StartThrottlingTimeouts();
   mWindow = nullptr;
   return NS_OK;
 }
 
 }
 
 bool
-TimeoutManager::BudgetThrottlingEnabled() const
+TimeoutManager::BudgetThrottlingEnabled(bool aIsBackground) const
 {
   // A window can be throttled using budget if
   // * It isn't active
   // * If it isn't using user media
   // * If it isn't using WebRTC
   // * If it hasn't got open WebSockets
   // * If it hasn't got active IndexedDB databases
-  //
+
   // Note that we allow both foreground and background to be
   // considered for budget throttling. What determines if they are if
-  // budget throttling is enabled is the regeneration factor.
+  // budget throttling is enabled is the max budget.
+  if ((aIsBackground ? gBackgroundThrottlingMaxBudget
+       : gForegroundThrottlingMaxBudget) < 0) {
+    return false;
+  }
 
   if (!mBudgetThrottleTimeouts || IsActive()) {
     return false;
   }
 
   // Check if there are any active IndexedDB databases
   if (mWindow.AsInner()->HasActiveIndexedDBDatabases()) {
     return false;
--- a/dom/base/TimeoutManager.h
+++ b/dom/base/TimeoutManager.h
@@ -143,17 +143,17 @@ private:
                          const TimeStamp& aNow = TimeStamp::Now());
 
   void RecordExecution(Timeout* aRunningTimeout,
                        Timeout* aTimeout);
 
   void UpdateBudget(const TimeStamp& aNow,
                     const TimeDuration& aDuration = TimeDuration());
 
-  bool BudgetThrottlingEnabled() const;
+  bool BudgetThrottlingEnabled(bool aIsBackground) const;
 
 private:
   struct Timeouts {
     explicit Timeouts(const TimeoutManager& aManager)
       : mManager(aManager)
     {
     }