Bug 1506976 - Make FirstContentfulPaint timing measure until the composite end of the paint. r=bas
authorMarkus Stange <mstange@themasta.com>
Tue, 12 Feb 2019 19:09:06 +0000
changeset 458779 c27aa490f40b
parent 458778 a98671536694
child 458780 2d0505c52681
push id35548
push useropoprus@mozilla.com
push dateWed, 13 Feb 2019 09:48:26 +0000
treeherdermozilla-central@93e37c529818 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1506976
milestone67.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 1506976 - Make FirstContentfulPaint timing measure until the composite end of the paint. r=bas 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
@@ -227,17 +227,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
@@ -2260,16 +2261,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;
   }
 
@@ -2540,22 +2551,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: