Bug 1506976 - Make FirstContentfulPaint timing measure until the composite end of the paint. r=bas, a=lizzard
authorMarkus Stange <mstange@themasta.com>
Tue, 12 Feb 2019 19:09:06 +0000
changeset 516003 1a21b29fb4bc5118d4d62e97364f41ec72c58001
parent 516002 4c4ff2febd8386343f67a62f08efab02f78e03f0
child 516004 c341768d99a4889091c5322e84ef5382302d3b7f
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas, lizzard
bugs1506976
milestone66.0
Bug 1506976 - Make FirstContentfulPaint timing measure until the composite end of the paint. r=bas, a=lizzard Differential Revision: https://phabricator.services.mozilla.com/D18880
dom/base/nsDOMNavigationTiming.cpp
dom/base/nsDOMNavigationTiming.h
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
--- a/dom/base/nsDOMNavigationTiming.cpp
+++ b/dom/base/nsDOMNavigationTiming.cpp
@@ -409,25 +409,26 @@ void nsDOMNavigationTiming::NotifyNonBla
           mNonBlankPaint);
     }
 
     Telemetry::AccumulateTimeDelta(Telemetry::TIME_TO_NON_BLANK_PAINT_MS,
                                    mNavigationStart, mNonBlankPaint);
   }
 }
 
-void nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument() {
+void nsDOMNavigationTiming::NotifyContentfulPaintForRootContentDocument(
+    const mozilla::TimeStamp& aCompositeEndTime) {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mNavigationStart.IsNull());
 
   if (!mContentfulPaint.IsNull()) {
     return;
   }
 
-  mContentfulPaint = TimeStamp::Now();
+  mContentfulPaint = aCompositeEndTime;
 
 #ifdef MOZ_GECKO_PROFILER
   if (profiler_is_active() || PAGELOAD_LOG_ENABLED()) {
     TimeDuration elapsed = mContentfulPaint - mNavigationStart;
     nsAutoCString spec;
     if (mLoadedURI) {
       mLoadedURI->GetSpec(spec);
     }
--- a/dom/base/nsDOMNavigationTiming.h
+++ b/dom/base/nsDOMNavigationTiming.h
@@ -137,17 +137,18 @@ class nsDOMNavigationTiming final : publ
   void NotifyDOMContentLoadedStart(nsIURI* aURI);
   void NotifyDOMContentLoadedEnd(nsIURI* aURI);
 
   static void TTITimeoutCallback(nsITimer* aTimer, void* aClosure);
   void TTITimeout(nsITimer* aTimer);
 
   void NotifyLongTask(mozilla::TimeStamp aWhen);
   void NotifyNonBlankPaintForRootContentDocument();
-  void NotifyContentfulPaintForRootContentDocument();
+  void NotifyContentfulPaintForRootContentDocument(
+      const mozilla::TimeStamp& aCompositeEndTime);
   void NotifyDOMContentFlushedForRootContentDocument();
   void NotifyDocShellStateChanged(DocShellState aDocShellState);
 
   DOMTimeMilliSec TimeStampToDOM(mozilla::TimeStamp aStamp) const;
 
   inline DOMHighResTimeStamp TimeStampToDOMHighRes(
       mozilla::TimeStamp aStamp) const {
     if (aStamp.IsNull()) {
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -232,17 +232,18 @@ nsPresContext::nsPresContext(dom::Docume
       mIsChromeOriginImage(false),
       mPaintFlashing(false),
       mPaintFlashingInitialized(false),
       mHasWarnedAboutPositionedTableParts(false),
       mHasWarnedAboutTooLargeDashedOrDottedRadius(false),
       mQuirkSheetAdded(false),
       mNeedsPrefUpdate(false),
       mHadNonBlankPaint(false),
-      mHadContentfulPaint(false)
+      mHadContentfulPaint(false),
+      mHadContentfulPaintComposite(false)
 #ifdef DEBUG
       ,
       mInitialized(false)
 #endif
 {
 #ifdef DEBUG
   PodZero(&mLayoutPhaseCount);
 #endif
@@ -2270,16 +2271,26 @@ void nsPresContext::NotifyRevokingDidPai
   NotifyDidPaintSubdocumentCallbackClosure closure = {aTransactionId,
                                                       mozilla::TimeStamp()};
   mDocument->EnumerateSubDocuments(
       nsPresContext::NotifyRevokingDidPaintSubdocumentCallback, &closure);
 }
 
 void nsPresContext::NotifyDidPaintForSubtree(
     TransactionId aTransactionId, const mozilla::TimeStamp& aTimeStamp) {
+  if (mFirstContentfulPaintTransactionId && !mHadContentfulPaintComposite) {
+    if (aTransactionId >= *mFirstContentfulPaintTransactionId) {
+      mHadContentfulPaintComposite = true;
+      RefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
+      if (timing) {
+        timing->NotifyContentfulPaintForRootContentDocument(aTimeStamp);
+      }
+    }
+  }
+
   if (IsRoot() && mTransactions.IsEmpty()) {
     return;
   }
 
   if (!PresShell()->IsVisible() && mTransactions.IsEmpty()) {
     return;
   }
 
@@ -2550,22 +2561,20 @@ void nsPresContext::NotifyNonBlankPaint(
     mFirstNonBlankPaintTime = TimeStamp::Now();
   }
 }
 
 void nsPresContext::NotifyContentfulPaint() {
   if (!mHadContentfulPaint) {
     mHadContentfulPaint = true;
     if (IsRootContentDocument()) {
-      RefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
-      if (timing) {
-        timing->NotifyContentfulPaintForRootContentDocument();
+      if (nsRootPresContext* rootPresContext = GetRootPresContext()) {
+        mFirstContentfulPaintTransactionId =
+            Some(rootPresContext->mRefreshDriver->LastTransactionId().Next());
       }
-
-      mFirstContentfulPaintTime = TimeStamp::Now();
     }
   }
 }
 
 void nsPresContext::NotifyDOMContentFlushed() {
   NS_ENSURE_TRUE_VOID(mShell);
   if (IsRootContentDocument()) {
     RefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -1260,24 +1260,26 @@ class nsPresContext : public nsISupports
   // 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;
 
+  mozilla::Maybe<TransactionId> mFirstContentfulPaintTransactionId;
+
   // Time of various first interaction types, used to report time from
   // first paint of the top level content pres shell to first interaction.
   mozilla::TimeStamp mFirstNonBlankPaintTime;
-  mozilla::TimeStamp mFirstContentfulPaintTime;
   mozilla::TimeStamp mFirstClickTime;
   mozilla::TimeStamp mFirstKeyTime;
   mozilla::TimeStamp mFirstMouseMoveTime;
   mozilla::TimeStamp mFirstScrollTime;
+
   bool mInteractionTimeEnabled;
 
   // last time we did a full style flush
   mozilla::TimeStamp mLastStyleUpdateForAllAnimations;
 
   unsigned mHasPendingInterrupt : 1;
   unsigned mPendingInterruptFromTest : 1;
   unsigned mInterruptsEnabled : 1;
@@ -1341,16 +1343,18 @@ class nsPresContext : public nsISupports
 
   // Is there a pref update to process once we have a container?
   unsigned mNeedsPrefUpdate : 1;
 
   // Has NotifyNonBlankPaint been called on this PresContext?
   unsigned mHadNonBlankPaint : 1;
   // Has NotifyContentfulPaint been called on this PresContext?
   unsigned mHadContentfulPaint : 1;
+  // Has NotifyDidPaintForSubtree been called for a contentful paint?
+  unsigned mHadContentfulPaintComposite : 1;
 
 #ifdef DEBUG
   unsigned mInitialized : 1;
 #endif
 
   mozilla::Maybe<mozilla::MediaFeatureChange> mPendingMediaFeatureValuesChange;
 
  protected: