Bug 1314314 - Restrict when idle callbacks are fired. r?bkelly draft
authorAndreas Farre <farre@mozilla.com>
Thu, 03 Nov 2016 18:47:23 +0100
changeset 433480 7b89ae22271976d0c1ea2cad5553a6f56f8e915f
parent 433441 92c5b8d103dd531deaf3715864a61239cd5d49df
child 535908 0930e8fe6fe2e9149b4a5adde38ca0005867356d
push id34600
push userbmo:afarre@mozilla.com
push dateThu, 03 Nov 2016 20:15:52 +0000
reviewersbkelly
bugs1314314
milestone52.0a1
Bug 1314314 - Restrict when idle callbacks are fired. r?bkelly MozReview-Commit-ID: L9ZTVFeHGTw
layout/base/nsLayoutUtils.cpp
modules/libpref/init/all.js
xpcom/threads/MainThreadIdlePeriod.cpp
xpcom/threads/MainThreadIdlePeriod.h
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -151,17 +151,17 @@ using namespace mozilla::gfx;
 #define FLOAT_LOGICAL_VALUES_ENABLED_PREF_NAME "layout.css.float-logical-values.enabled"
 #define BG_CLIP_TEXT_ENABLED_PREF_NAME "layout.css.background-clip-text.enabled"
 
 // The time in number of frames that we estimate for a refresh driver
 // to be quiescent
 #define DEFAULT_QUIESCENT_FRAMES 2
 // The time (milliseconds) we estimate is needed between the end of an
 // idle time and the next Tick.
-#define DEFAULT_IDLE_PERIOD_TIME_LIMIT 3.0f
+#define DEFAULT_IDLE_PERIOD_TIME_LIMIT 1.0f
 
 #ifdef DEBUG
 // TODO: remove, see bug 598468.
 bool nsLayoutUtils::gPreventAssertInCompareTreePosition = false;
 #endif // DEBUG
 
 typedef FrameMetrics::ViewID ViewID;
 typedef nsStyleTransformMatrix::TransformReferenceBox TransformReferenceBox;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -2684,17 +2684,17 @@ pref("layout.spammy_warnings.enabled", f
 pref("layout.float-fragments-inside-column.enabled", true);
 
 // The number of frames times the frame rate is the time required to
 // pass without painting used to guess that we'll not paint again soon
 pref("layout.idle_period.required_quiescent_frames", 2);
 
 // The amount of time (milliseconds) needed between an idle period's
 // end and the start of the next tick to avoid jank.
-pref("layout.idle_period.time_limit", 3);
+pref("layout.idle_period.time_limit", 1);
 
 // Is support for the Web Animations API enabled?
 // Before enabling this by default, make sure also CSSPseudoElement interface
 // has been spec'ed properly, or we should add a separate pref for
 // CSSPseudoElement interface. See Bug 1174575 for further details.
 #ifdef RELEASE_OR_BETA
 pref("dom.animations-api.core.enabled", false);
 #else
@@ -2741,16 +2741,24 @@ pref("dom.global_stop_script", true);
 pref("dom.archivereader.enabled", false);
 
 // Time (milliseconds) between throttled idle callbacks.
 pref("dom.idle_period.throttled_length", 10000);
 
 // The amount of idle time (milliseconds) reserved for a long idle period
 pref("idle_queue.long_period", 50);
 
+// The minimum amount of time (milliseconds) required for an idle
+// period to be scheduled on the main thread. N.B. that
+// layout.idle_period.time_limit adds padding at the end of the idle
+// period, which makes the point in time that we expect to become busy
+// again be:
+// now + idle_queue.min_period + layout.idle_period.time_limit
+pref("idle_queue.min_period", 3);
+
 // Hang monitor timeout after which we kill the browser, in seconds
 // (0 is disabled)
 // Disabled on all platforms per bug 705748 until the found issues are
 // resolved.
 pref("hangmonitor.timeout", 0);
 
 pref("plugins.load_appdir_plugins", false);
 // If true, plugins will be click to play
--- a/xpcom/threads/MainThreadIdlePeriod.cpp
+++ b/xpcom/threads/MainThreadIdlePeriod.cpp
@@ -6,44 +6,71 @@
 
 #include "MainThreadIdlePeriod.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/Preferences.h"
 #include "nsRefreshDriver.h"
 
 #define DEFAULT_LONG_IDLE_PERIOD 50.0f
+#define DEFAULT_MIN_IDLE_PERIOD 3.0f
 
 namespace mozilla {
 
 NS_IMETHODIMP
 MainThreadIdlePeriod::GetIdlePeriodHint(TimeStamp* aIdleDeadline)
 {
+  MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aIdleDeadline);
 
   Maybe<TimeStamp> deadline = nsRefreshDriver::GetIdleDeadlineHint();
 
   if (deadline.isSome()) {
-    *aIdleDeadline = deadline.value();
+    // If the idle period is too small, then just return a null time
+    // to indicate we are busy. Otherwise return the actual deadline.
+    TimeDuration minIdlePeriod =
+      TimeDuration::FromMilliseconds(GetMinIdlePeriod());
+    bool busySoon = deadline.value().IsNull() ||
+                    (TimeStamp::Now() >= (deadline.value() - minIdlePeriod));
+    *aIdleDeadline = busySoon ? TimeStamp() : deadline.value();
   } else {
     *aIdleDeadline =
       TimeStamp::Now() + TimeDuration::FromMilliseconds(GetLongIdlePeriod());
   }
 
   return NS_OK;
 }
 
 /* static */ float
 MainThreadIdlePeriod::GetLongIdlePeriod()
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   static float sLongIdlePeriod = DEFAULT_LONG_IDLE_PERIOD;
   static bool sInitialized = false;
 
   if (!sInitialized && Preferences::IsServiceAvailable()) {
     sInitialized = true;
     Preferences::AddFloatVarCache(&sLongIdlePeriod, "idle_queue.long_period",
                                   DEFAULT_LONG_IDLE_PERIOD);
   }
 
   return sLongIdlePeriod;
 }
 
+/* static */ float
+MainThreadIdlePeriod::GetMinIdlePeriod()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  static float sMinIdlePeriod = DEFAULT_MIN_IDLE_PERIOD;
+  static bool sInitialized = false;
+
+  if (!sInitialized && Preferences::IsServiceAvailable()) {
+    sInitialized = true;
+    Preferences::AddFloatVarCache(&sMinIdlePeriod, "idle_queue.min_period",
+                                  DEFAULT_MIN_IDLE_PERIOD);
+  }
+
+  return sMinIdlePeriod;
+}
+
 } // namespace mozilla
--- a/xpcom/threads/MainThreadIdlePeriod.h
+++ b/xpcom/threads/MainThreadIdlePeriod.h
@@ -13,15 +13,16 @@
 namespace mozilla {
 
 class MainThreadIdlePeriod final : public IdlePeriod
 {
 public:
   NS_DECL_NSIIDLEPERIOD
 
   static float GetLongIdlePeriod();
+  static float GetMinIdlePeriod();
 private:
   virtual ~MainThreadIdlePeriod() {}
 };
 
 } // namespace mozilla
 
 #endif // mozilla_dom_mainthreadidleperiod_h