Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(707)

Unified Diff: third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp

Issue 2711893002: Loosen FirstMeaningfulPaint UMA network-idle heuristics (Closed)
Patch Set: add tests, rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp
diff --git a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp
index 9fca4136977ee48f1cbc383fcf7596b21f0748de..c544c7ad14ef81fd575fbe9cc04b61b1bbb8ea24 100644
--- a/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp
+++ b/third_party/WebKit/Source/core/paint/FirstMeaningfulPaintDetector.cpp
@@ -7,6 +7,7 @@
#include "core/css/FontFaceSet.h"
#include "core/dom/TaskRunnerHelper.h"
#include "core/paint/PaintTiming.h"
+#include "platform/Histogram.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/loader/fetch/ResourceFetcher.h"
@@ -18,9 +19,10 @@ namespace {
// Meaningful Paint.
const int kBlankCharactersThreshold = 200;
-// FirstMeaningfulPaintDetector stops observing layouts and reports First
-// Meaningful Paint when this duration passed from last network activity.
-const double kSecondsWithoutNetworkActivityThreshold = 0.5;
+// The page is n-quiet if there are no more than n active network requests for
+// this duration of time.
+const double kNetwork2QuietWindowSeconds = 3;
+const double kNetwork0QuietWindowSeconds = 0.5;
} // namespace
@@ -33,10 +35,14 @@ FirstMeaningfulPaintDetector::FirstMeaningfulPaintDetector(
PaintTiming* paintTiming,
Document& document)
: m_paintTiming(paintTiming),
- m_networkStableTimer(
+ m_network0QuietTimer(
TaskRunnerHelper::get(TaskType::UnspecedTimer, &document),
this,
- &FirstMeaningfulPaintDetector::networkStableTimerFired) {}
+ &FirstMeaningfulPaintDetector::network0QuietTimerFired),
+ m_network2QuietTimer(
+ TaskRunnerHelper::get(TaskType::UnspecedTimer, &document),
+ this,
+ &FirstMeaningfulPaintDetector::network2QuietTimerFired) {}
Document* FirstMeaningfulPaintDetector::document() {
return m_paintTiming->supplementable();
@@ -52,7 +58,7 @@ void FirstMeaningfulPaintDetector::markNextPaintAsMeaningfulIfNeeded(
int contentsHeightBeforeLayout,
int contentsHeightAfterLayout,
int visibleHeight) {
- if (m_state == Reported)
+ if (m_network0QuietReached && m_network2QuietReached)
return;
unsigned delta = counter.count() - m_prevLayoutObjectCount;
@@ -77,14 +83,14 @@ void FirstMeaningfulPaintDetector::markNextPaintAsMeaningfulIfNeeded(
significance += m_accumulatedSignificanceWhileHavingBlankText;
m_accumulatedSignificanceWhileHavingBlankText = 0;
if (significance > m_maxSignificanceSoFar) {
- m_state = NextPaintIsMeaningful;
+ m_nextPaintIsMeaningful = true;
m_maxSignificanceSoFar = significance;
}
}
}
void FirstMeaningfulPaintDetector::notifyPaint() {
- if (m_state != NextPaintIsMeaningful)
+ if (!m_nextPaintIsMeaningful)
return;
// Skip document background-only paints.
@@ -92,7 +98,10 @@ void FirstMeaningfulPaintDetector::notifyPaint() {
return;
m_provisionalFirstMeaningfulPaint = monotonicallyIncreasingTime();
- m_state = NextPaintIsNotMeaningful;
+ m_nextPaintIsMeaningful = false;
+
+ if (m_network2QuietReached)
+ return;
TRACE_EVENT_MARK_WITH_TIMESTAMP1(
"loading", "firstMeaningfulPaintCandidate",
@@ -107,28 +116,94 @@ void FirstMeaningfulPaintDetector::notifyPaint() {
m_paintTiming->markFirstMeaningfulPaintCandidate();
}
-void FirstMeaningfulPaintDetector::checkNetworkStable() {
+bool FirstMeaningfulPaintDetector::isNetworkQuiet(int maxActiveConnections) {
DCHECK(document());
- if (m_state == Reported || document()->fetcher()->hasPendingRequest())
+ if (!document()->hasFinishedParsing())
+ return false;
+ ResourceFetcher* fetcher = document()->fetcher();
+ return fetcher->blockingRequestCount() + fetcher->nonblockingRequestCount() <=
+ maxActiveConnections;
+}
+
+void FirstMeaningfulPaintDetector::checkNetworkStable() {
+ if (!m_network0QuietReached && isNetworkQuiet(0)) {
+ m_network0QuietTimer.startOneShot(kNetwork0QuietWindowSeconds,
+ BLINK_FROM_HERE);
+ }
+ if (!m_network2QuietReached && isNetworkQuiet(2)) {
+ m_network2QuietTimer.startOneShot(kNetwork2QuietWindowSeconds,
+ BLINK_FROM_HERE);
+ }
+}
+
+void FirstMeaningfulPaintDetector::network0QuietTimerFired(TimerBase*) {
+ if (!document() || m_network0QuietReached || !isNetworkQuiet(0) ||
+ !m_paintTiming->firstContentfulPaint())
return;
+ m_network0QuietReached = true;
- m_networkStableTimer.startOneShot(kSecondsWithoutNetworkActivityThreshold,
- BLINK_FROM_HERE);
+ if (m_provisionalFirstMeaningfulPaint) {
+ // Enforce FirstContentfulPaint <= FirstMeaningfulPaint.
+ m_firstMeaningfulPaint0Quiet =
+ std::max(m_provisionalFirstMeaningfulPaint,
+ m_paintTiming->firstContentfulPaint());
+ }
+ reportHistograms();
}
-void FirstMeaningfulPaintDetector::networkStableTimerFired(TimerBase*) {
- if (m_state == Reported || !document() ||
- document()->fetcher()->hasPendingRequest() ||
+void FirstMeaningfulPaintDetector::network2QuietTimerFired(TimerBase*) {
+ if (!document() || m_network2QuietReached || !isNetworkQuiet(2) ||
!m_paintTiming->firstContentfulPaint())
return;
+ m_network2QuietReached = true;
if (m_provisionalFirstMeaningfulPaint) {
// Enforce FirstContentfulPaint <= FirstMeaningfulPaint.
- double timestamp = std::max(m_provisionalFirstMeaningfulPaint,
- m_paintTiming->firstContentfulPaint());
- m_paintTiming->setFirstMeaningfulPaint(timestamp);
+ m_firstMeaningfulPaint2Quiet =
+ std::max(m_provisionalFirstMeaningfulPaint,
+ m_paintTiming->firstContentfulPaint());
+ // Report FirstMeaningfulPaint when the page reached network 2-quiet.
+ m_paintTiming->setFirstMeaningfulPaint(m_firstMeaningfulPaint2Quiet);
+ }
+ reportHistograms();
+}
+
+void FirstMeaningfulPaintDetector::reportHistograms() {
+ enum HadNetworkQuiet {
Ilya Sherman 2017/03/08 09:19:46 Please document that this enum should be treated a
Kunihiko Sakamoto 2017/03/08 10:16:10 Done.
+ HadNetwork0Quiet,
+ HadNetwork2Quiet,
+ HadNetworkQuietEnumMax
+ };
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram, hadNetworkQuietHistogram,
+ ("FirstMeaningfulPaintDetector.HadNetworkQuiet", HadNetworkQuietEnumMax));
+
+ enum FMPOrderingEnum {
Ilya Sherman 2017/03/08 09:19:46 And this one too =)
Kunihiko Sakamoto 2017/03/08 10:16:10 Done.
+ FMP0QuietFirst,
+ FMP2QuietFirst,
+ FMP0QuietEqualFMP2Quiet,
+ FMPOrderingEnumMax
+ };
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram, firstMeaningfulPaintOrderingHistogram,
+ ("FirstMeaningfulPaintDetector.FirstMeaningfulPaintOrdering",
+ FMPOrderingEnumMax));
+
+ if (m_firstMeaningfulPaint0Quiet && m_firstMeaningfulPaint2Quiet) {
+ int sample;
+ if (m_firstMeaningfulPaint2Quiet < m_firstMeaningfulPaint0Quiet) {
+ sample = FMP0QuietFirst;
+ } else if (m_firstMeaningfulPaint2Quiet > m_firstMeaningfulPaint0Quiet) {
+ sample = FMP2QuietFirst;
+ } else {
+ sample = FMP0QuietEqualFMP2Quiet;
+ }
+ firstMeaningfulPaintOrderingHistogram.count(sample);
+ } else if (m_firstMeaningfulPaint0Quiet) {
+ hadNetworkQuietHistogram.count(HadNetwork0Quiet);
+ } else if (m_firstMeaningfulPaint2Quiet) {
+ hadNetworkQuietHistogram.count(HadNetwork2Quiet);
}
- m_state = Reported;
}
DEFINE_TRACE(FirstMeaningfulPaintDetector) {

Powered by Google App Engine
This is Rietveld 408576698