Bug 1336598 P3 Add preferences to control timeout back pressure algorithm. r=smaug
authorBen Kelly <ben@wanderview.com>
Sun, 05 Feb 2017 21:50:12 -0500
changeset 340893 ca7ec2dd740d65b6f65a7f9d3802c2494871833a
parent 340892 79f1f1073258c46ff20721551ce4b604312f2571
child 340894 dfcd7fa37af1a07dbe2d221735bcb192ad4c43e7
push id31318
push usercbook@mozilla.com
push dateMon, 06 Feb 2017 11:56:59 +0000
treeherdermozilla-central@1cc159c7a044 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1336598
milestone54.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 1336598 P3 Add preferences to control timeout back pressure algorithm. r=smaug
dom/base/TimeoutManager.cpp
--- a/dom/base/TimeoutManager.cpp
+++ b/dom/base/TimeoutManager.cpp
@@ -62,52 +62,56 @@ static int32_t gTimeoutBucketingStrategy
 #define DOM_MAX_TIMEOUT_VALUE    DELAY_INTERVAL_LIMIT
 
 uint32_t TimeoutManager::sNestingLevel = 0;
 
 namespace {
 
 // The number of queued runnables within the TabGroup ThrottledEventQueue
 // at which to begin applying back pressure to the window.
-const uint32_t kThrottledEventQueueBackPressure = 5000;
+#define DEFAULT_THROTTLED_EVENT_QUEUE_BACK_PRESSURE 5000
+static uint32_t gThrottledEventQueueBackPressure;
 
 // The amount of delay to apply to timers when back pressure is triggered.
 // As the length of the ThrottledEventQueue grows delay is increased.  The
 // delay is scaled such that every kThrottledEventQueueBackPressure runnables
 // in the queue equates to an additional kBackPressureDelayMS.
-const double kBackPressureDelayMS = 250;
+#define DEFAULT_BACK_PRESSURE_DELAY_MS 250
+static uint32_t gBackPressureDelayMS;
 
 // This defines a limit for how much the delay must drop before we actually
 // reduce back pressure throttle amount.  This makes the throttle delay
 // a bit "sticky" once we enter back pressure.
-const double kBackPressureDelayReductionThresholdMS = 1000;
+#define DEFAULT_BACK_PRESSURE_DELAY_REDUCTION_THRESHOLD_MS 1000
+static uint32_t gBackPressureDelayReductionThresholdMS;
 
 // The minimum delay we can reduce back pressure to before we just floor
 // the value back to zero.  This allows us to ensure that we can exit
 // back pressure event if there are always a small number of runnables
 // queued up.
-const double kBackPressureDelayMinimumMS = 100;
+#define DEFAULT_BACK_PRESSURE_DELAY_MINIMUM_MS 100
+static uint32_t gBackPressureDelayMinimumMS;
 
 // Convert a ThrottledEventQueue length to a timer delay in milliseconds.
 // This will return a value between 0 and INT32_MAX.
 int32_t
 CalculateNewBackPressureDelayMS(uint32_t aBacklogDepth)
 {
   double multiplier = static_cast<double>(aBacklogDepth) /
-                      static_cast<double>(kThrottledEventQueueBackPressure);
-  double value = kBackPressureDelayMS * multiplier;
+                      static_cast<double>(gThrottledEventQueueBackPressure);
+  double value = static_cast<double>(gBackPressureDelayMS) * multiplier;
   // Avoid overflow
   if (value > INT32_MAX) {
     value = INT32_MAX;
   }
 
   // Once we get close to an empty queue just floor the delay back to zero.
   // We want to ensure we don't get stuck in a condition where there is a
   // small amount of delay remaining due to an active, but reasonable, queue.
-  else if (value < kBackPressureDelayMinimumMS) {
+  else if (value < static_cast<double>(gBackPressureDelayMinimumMS)) {
     value = 0;
   }
   return static_cast<int32_t>(value);
 }
 
 } // anonymous namespace
 
 TimeoutManager::TimeoutManager(nsGlobalWindow& aWindow)
@@ -148,16 +152,29 @@ TimeoutManager::Initialize()
                               "dom.min_tracking_background_timeout_value",
                               DEFAULT_MIN_TRACKING_BACKGROUND_TIMEOUT_VALUE);
   Preferences::AddIntVarCache(&gTimeoutBucketingStrategy,
                               "dom.timeout_bucketing_strategy",
                               TRACKING_SEPARATE_TIMEOUT_BUCKETING_STRATEGY);
   Preferences::AddBoolVarCache(&gAnnotateTrackingChannels,
                                "privacy.trackingprotection.annotate_channels",
                                false);
+
+  Preferences::AddUintVarCache(&gThrottledEventQueueBackPressure,
+                               "dom.timeout.throttled_event_queue_back_pressure",
+                               DEFAULT_THROTTLED_EVENT_QUEUE_BACK_PRESSURE);
+  Preferences::AddUintVarCache(&gBackPressureDelayMS,
+                               "dom.timeout.back_pressure_delay_ms",
+                               DEFAULT_BACK_PRESSURE_DELAY_MS);
+  Preferences::AddUintVarCache(&gBackPressureDelayReductionThresholdMS,
+                               "dom.timeout.back_pressure_delay_reduction_threshold_ms",
+                               DEFAULT_BACK_PRESSURE_DELAY_REDUCTION_THRESHOLD_MS);
+  Preferences::AddUintVarCache(&gBackPressureDelayMinimumMS,
+                               "dom.timeout.back_pressure_delay_minimum_ms",
+                               DEFAULT_BACK_PRESSURE_DELAY_MINIMUM_MS);
 }
 
 uint32_t
 TimeoutManager::GetTimeoutId(Timeout::Reason aReason)
 {
   switch (aReason) {
     case Timeout::Reason::eIdleCallbackTimeout:
       return ++mIdleCallbackTimeoutCounter;
@@ -649,17 +666,17 @@ TimeoutManager::MaybeApplyBackPressure()
     return;
   }
 
   // Only begin back pressure if the window has greatly fallen behind the main
   // thread.  This is a somewhat arbitrary threshold chosen such that it should
   // rarely fire under normaly circumstances.  Its low enough, though,
   // that we should have time to slow new runnables from being added before an
   // OOM occurs.
-  if (queue->Length() < kThrottledEventQueueBackPressure) {
+  if (queue->Length() < gThrottledEventQueueBackPressure) {
     return;
   }
 
   // First attempt to dispatch a runnable to update our back pressure state.  We
   // do this first in order to verify we can dispatch successfully before
   // entering the back pressure state.
   nsCOMPtr<nsIRunnable> r =
     NewNonOwningRunnableMethod<StoreRefPtrPassByPtr<nsGlobalWindow>>(this,
@@ -707,18 +724,18 @@ TimeoutManager::CancelOrUpdateBackPressu
 
   // If the delay has decreased, though, we only apply the new value if it has
   // reduced significantly.  This hysteresis avoids thrashing the back pressure
   // value back and forth rapidly.  This is important because reducing the
   // backpressure delay requires calling ResetTimerForThrottleReduction() which
   // can be quite expensive.  We only want to call that method if the back log
   // is really clearing.
   else if (newBackPressureDelayMS == 0 ||
-           (mBackPressureDelayMS >
-           (newBackPressureDelayMS + kBackPressureDelayReductionThresholdMS))) {
+           (static_cast<uint32_t>(mBackPressureDelayMS) >
+           (newBackPressureDelayMS + gBackPressureDelayReductionThresholdMS))) {
     int32_t oldBackPressureDelayMS = mBackPressureDelayMS;
     mBackPressureDelayMS = newBackPressureDelayMS;
 
     // If the back pressure delay has gone down we must reset any existing
     // timers to use the new value.  Otherwise we run the risk of executing
     // timer callbacks out-of-order.
     ResetTimersForThrottleReduction(oldBackPressureDelayMS);
   }