Bug 1538517, use higher frame rate right after first contentful paint, r=farre
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 26 Mar 2019 20:47:50 +0000
changeset 466218 224337be28e3833cc815c043644ce4a75e168cfc
parent 466217 942fd44a3510b0a2b03d893e621f8229b49f2205
child 466219 48e6a07862e0c79ecac3aa7dc826a2f3e42bb98f
push id35762
push usercsabou@mozilla.com
push dateWed, 27 Mar 2019 04:44:00 +0000
treeherdermozilla-central@bc572aee49b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfarre
bugs1538517
milestone68.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 1538517, use higher frame rate right after first contentful paint, r=farre fcp is often almost blank paint, but the next couple paints have more content. But in order to not regress page load time, reduce frame rate later during the page load. Differential Revision: https://phabricator.services.mozilla.com/D24636
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsRefreshDriver.cpp
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -158,16 +158,17 @@ nsPresContext::nsPresContext(dom::Docume
       mPageScale(0.0),
       mPPScale(1.0f),
       mViewportScrollOverrideElement(nullptr),
       mViewportScrollStyles(StyleOverflow::Auto, StyleOverflow::Auto),
       mExistThrottledUpdates(false),
       // mImageAnimationMode is initialised below, in constructor body
       mImageAnimationModePref(imgIContainer::kNormalAnimMode),
       mInterruptChecksToSkip(0),
+      mNextFrameRateMultiplier(0),
       mElementsRestyled(0),
       mFramesConstructed(0),
       mFramesReflowed(0),
       mInteractionTimeEnabled(true),
       mHasPendingInterrupt(false),
       mPendingInterruptFromTest(false),
       mInterruptsEnabled(false),
       mSendAfterPaintToContent(false),
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1067,16 +1067,28 @@ class nsPresContext : public nsISupports
    * Checks for MozAfterPaint listeners on the document and
    * any subdocuments, except for subdocuments that are non-top-level
    * content documents.
    */
   bool MayHavePaintEventListenerInSubDocument();
 
   void InvalidatePaintedLayers();
 
+  uint32_t GetNextFrameRateMultiplier() const {
+    return mNextFrameRateMultiplier;
+  }
+
+  void DidUseFrameRateMultiplier() {
+    if (!mNextFrameRateMultiplier) {
+      mNextFrameRateMultiplier = 1;
+    } else if (mNextFrameRateMultiplier < 8) {
+      mNextFrameRateMultiplier = mNextFrameRateMultiplier * 2;
+    }
+  }
+
  protected:
   // May be called multiple times (unlink, destructor)
   void Destroy();
 
   void AppUnitsPerDevPixelChanged();
 
   bool HavePendingInputEvent();
 
@@ -1171,16 +1183,19 @@ class nsPresContext : public nsISupports
 
   bool mExistThrottledUpdates;
 
   uint16_t mImageAnimationMode;
   uint16_t mImageAnimationModePref;
 
   uint32_t mInterruptChecksToSkip;
 
+  // During page load we use slower frame rate.
+  uint32_t mNextFrameRateMultiplier;
+
   // Counters for tests and tools that want to detect frame construction
   // or reflow.
   uint64_t mElementsRestyled;
   uint64_t mFramesConstructed;
   uint64_t mFramesReflowed;
 
   mozilla::TimeStamp mReflowStartTime;
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -559,28 +559,34 @@ class VsyncRefreshDriverTimer : public R
 
         if (StaticPrefs::layout_lower_priority_refresh_driver_during_load()) {
           nsPresContext* pctx =
               mVsyncRefreshDriverTimer->GetPresContextForOnlyRefreshDriver();
           if (pctx && pctx->HadContentfulPaint() && pctx->Document() &&
               pctx->Document()->GetReadyStateEnum() <
                   Document::READYSTATE_COMPLETE) {
             nsPIDOMWindowInner* win = pctx->Document()->GetInnerWindow();
-            if (win) {
+            uint32_t frameRateMultiplier = pctx->GetNextFrameRateMultiplier();
+            if (!frameRateMultiplier) {
+              pctx->DidUseFrameRateMultiplier();
+            }
+            if (win && frameRateMultiplier) {
               dom::Performance* perf = win->GetPerformance();
               // Limit slower refresh rate to 5 seconds between the
               // first contentful paint and page load.
               if (perf && perf->Now() < 5000) {
                 if (mProcessedVsync) {
                   mProcessedVsync = false;
                   // Handle this case similarly to the code above, but just
                   // use idle queue.
                   TimeDuration rate = mVsyncRefreshDriverTimer->GetTimerRate();
                   uint32_t slowRate =
-                      static_cast<uint32_t>(rate.ToMilliseconds() * 4);
+                      static_cast<uint32_t>(rate.ToMilliseconds() *
+                                            frameRateMultiplier);
+                  pctx->DidUseFrameRateMultiplier();
                   nsCOMPtr<nsIRunnable> vsyncEvent = NewRunnableMethod<>(
                       "RefreshDriverVsyncObserver::NormalPriorityNotify[IDLE]",
                       this, &RefreshDriverVsyncObserver::NormalPriorityNotify);
                   NS_DispatchToCurrentThreadQueue(vsyncEvent.forget(), slowRate,
                                                   EventQueuePriority::Idle);
                 }
                 return true;
               }