Commit 8cbfef6a authored by Nicolás Peña Moreno's avatar Nicolás Peña Moreno Committed by Commit Bot

Use FCP instead of FMP in Time To Interactive

In this CL, we change the InteractiveDetector to rely on FCP instead of
FMP for TTI computations. In addition to this, the invalidating input
before FMP was only being used to determine whether to plumb TTI to the
browser process. As this is now never being done, that field can be
removed. The InteractiveDetectorTest is changed accordingly.

Bug: 1055806
Change-Id: Ie0154ffca8c79a0896679278c671e57668d0aa49
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2076057Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Reviewed-by: default avatarDeep Roy <dproy@chromium.org>
Commit-Queue: Nicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745137}
parent 427eaca9
...@@ -129,24 +129,6 @@ void InteractiveDetector::StartOrPostponeCITimer( ...@@ -129,24 +129,6 @@ void InteractiveDetector::StartOrPostponeCITimer(
} }
} }
base::TimeTicks InteractiveDetector::GetInteractiveTime() const {
// TODO(crbug.com/808685) Simplify FMP and TTI input invalidation.
return page_event_times_.first_meaningful_paint_invalidated
? base::TimeTicks()
: interactive_time_;
}
base::TimeTicks InteractiveDetector::GetInteractiveDetectionTime() const {
// TODO(crbug.com/808685) Simplify FMP and TTI input invalidation.
return page_event_times_.first_meaningful_paint_invalidated
? base::TimeTicks()
: interactive_detection_time_;
}
base::TimeTicks InteractiveDetector::GetFirstInvalidatingInputTime() const {
return page_event_times_.first_invalidating_input;
}
base::TimeDelta InteractiveDetector::GetFirstInputDelay() const { base::TimeDelta InteractiveDetector::GetFirstInputDelay() const {
return page_event_times_.first_input_delay; return page_event_times_.first_input_delay;
} }
...@@ -373,19 +355,16 @@ void InteractiveDetector::OnLongTaskDetected(base::TimeTicks start_time, ...@@ -373,19 +355,16 @@ void InteractiveDetector::OnLongTaskDetected(base::TimeTicks start_time,
StartOrPostponeCITimer(end_time + kTimeToInteractiveWindow); StartOrPostponeCITimer(end_time + kTimeToInteractiveWindow);
} }
void InteractiveDetector::OnFirstMeaningfulPaintDetected( void InteractiveDetector::OnFirstContentfulPaint(
base::TimeTicks fmp_time, base::TimeTicks first_contentful_paint) {
FirstMeaningfulPaintDetector::HadUserInput user_input_before_fmp) { // Should not set FCP twice.
DCHECK(page_event_times_.first_meaningful_paint DCHECK(page_event_times_.first_contentful_paint.is_null());
.is_null()); // Should not set FMP twice. page_event_times_.first_contentful_paint = first_contentful_paint;
page_event_times_.first_meaningful_paint = fmp_time; if (clock_->NowTicks() - first_contentful_paint >= kTimeToInteractiveWindow) {
page_event_times_.first_meaningful_paint_invalidated = // We may have reached TTI already. Check right away.
user_input_before_fmp == FirstMeaningfulPaintDetector::kHadUserInput;
if (clock_->NowTicks() - fmp_time >= kTimeToInteractiveWindow) {
// We may have reached TTCI already. Check right away.
CheckTimeToInteractiveReached(); CheckTimeToInteractiveReached();
} else { } else {
StartOrPostponeCITimer(page_event_times_.first_meaningful_paint + StartOrPostponeCITimer(page_event_times_.first_contentful_paint +
kTimeToInteractiveWindow); kTimeToInteractiveWindow);
} }
} }
...@@ -521,21 +500,21 @@ void InteractiveDetector::CheckTimeToInteractiveReached() { ...@@ -521,21 +500,21 @@ void InteractiveDetector::CheckTimeToInteractiveReached() {
if (!interactive_time_.is_null()) if (!interactive_time_.is_null())
return; return;
// FMP and DCL have not been detected yet. // FCP and DCL have not been detected yet.
if (page_event_times_.first_meaningful_paint.is_null() || if (page_event_times_.first_contentful_paint.is_null() ||
page_event_times_.dom_content_loaded_end.is_null()) page_event_times_.dom_content_loaded_end.is_null())
return; return;
const base::TimeTicks current_time = clock_->NowTicks(); const base::TimeTicks current_time = clock_->NowTicks();
if (current_time - page_event_times_.first_meaningful_paint < if (current_time - page_event_times_.first_contentful_paint <
kTimeToInteractiveWindow) { kTimeToInteractiveWindow) {
// Too close to FMP to determine Time to Interactive. // Too close to FCP to determine Time to Interactive.
return; return;
} }
AddCurrentlyActiveQuietIntervals(current_time); AddCurrentlyActiveQuietIntervals(current_time);
const base::TimeTicks interactive_candidate = const base::TimeTicks interactive_candidate =
FindInteractiveCandidate(page_event_times_.first_meaningful_paint); FindInteractiveCandidate(page_event_times_.first_contentful_paint);
RemoveCurrentlyActiveQuietIntervals(); RemoveCurrentlyActiveQuietIntervals();
// No Interactive Candidate found. // No Interactive Candidate found.
...@@ -563,14 +542,6 @@ void InteractiveDetector::OnTimeToInteractiveDetected() { ...@@ -563,14 +542,6 @@ void InteractiveDetector::OnTimeToInteractiveDetected() {
"loading,rail", "InteractiveTime", interactive_time_, "frame", "loading,rail", "InteractiveTime", interactive_time_, "frame",
ToTraceValue(GetSupplementable()->GetFrame()), ToTraceValue(GetSupplementable()->GetFrame()),
"had_user_input_before_interactive", had_user_input_before_interactive); "had_user_input_before_interactive", had_user_input_before_interactive);
// We only send TTI to Performance Timing Observers if FMP was not invalidated
// by input.
// TODO(crbug.com/808685) Simplify FMP and TTI input invalidation.
if (!page_event_times_.first_meaningful_paint_invalidated) {
if (GetSupplementable()->Loader())
GetSupplementable()->Loader()->DidChangePerformanceTiming();
}
} }
void InteractiveDetector::ContextDestroyed() { void InteractiveDetector::ContextDestroyed() {
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/loader/long_task_detector.h" #include "third_party/blink/renderer/core/loader/long_task_detector.h"
#include "third_party/blink/renderer/core/page/page_hidden_state.h" #include "third_party/blink/renderer/core/page/page_hidden_state.h"
#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/supplementable.h" #include "third_party/blink/renderer/platform/supplementable.h"
...@@ -78,25 +77,11 @@ class CORE_EXPORT InteractiveDetector ...@@ -78,25 +77,11 @@ class CORE_EXPORT InteractiveDetector
void OnResourceLoadEnd(base::Optional<base::TimeTicks> load_finish_time); void OnResourceLoadEnd(base::Optional<base::TimeTicks> load_finish_time);
void SetNavigationStartTime(base::TimeTicks navigation_start_time); void SetNavigationStartTime(base::TimeTicks navigation_start_time);
void OnFirstMeaningfulPaintDetected( void OnFirstContentfulPaint(base::TimeTicks first_contentful_paint);
base::TimeTicks fmp_time,
FirstMeaningfulPaintDetector::HadUserInput user_input_before_fmp);
void OnDomContentLoadedEnd(base::TimeTicks dcl_time); void OnDomContentLoadedEnd(base::TimeTicks dcl_time);
void OnInvalidatingInputEvent(base::TimeTicks invalidation_time); void OnInvalidatingInputEvent(base::TimeTicks invalidation_time);
void OnPageHiddenChanged(bool is_hidden); void OnPageHiddenChanged(bool is_hidden);
// Returns Interactive Time if already detected, or 0.0 otherwise.
base::TimeTicks GetInteractiveTime() const;
// Returns the time when page interactive was detected. The detection time can
// be useful to make decisions about metric invalidation in scenarios like tab
// backgrounding.
base::TimeTicks GetInteractiveDetectionTime() const;
// Returns the first time interactive detector received a significant input
// that may cause observers to discard the interactive time value.
base::TimeTicks GetFirstInvalidatingInputTime() const;
// The duration between the hardware timestamp and being queued on the main // The duration between the hardware timestamp and being queued on the main
// thread for the first click, tap, key press, cancelable touchstart, or // thread for the first click, tap, key press, cancelable touchstart, or
// pointer down followed by a pointer up. // pointer down followed by a pointer up.
...@@ -154,9 +139,12 @@ class CORE_EXPORT InteractiveDetector ...@@ -154,9 +139,12 @@ class CORE_EXPORT InteractiveDetector
// Page event times that Interactive Detector depends on. // Page event times that Interactive Detector depends on.
// Null base::TimeTicks values indicate the event has not been detected yet. // Null base::TimeTicks values indicate the event has not been detected yet.
struct { struct {
base::TimeTicks first_meaningful_paint; base::TimeTicks first_contentful_paint;
base::TimeTicks dom_content_loaded_end; base::TimeTicks dom_content_loaded_end;
base::TimeTicks nav_start; base::TimeTicks nav_start;
// The timestamp of the first input that would invalidate a Time to
// Interactive computation. This is used when reporting Time To Interactive
// on a trace event.
base::TimeTicks first_invalidating_input; base::TimeTicks first_invalidating_input;
base::TimeDelta first_input_delay; base::TimeDelta first_input_delay;
base::TimeDelta longest_input_delay; base::TimeDelta longest_input_delay;
...@@ -165,7 +153,6 @@ class CORE_EXPORT InteractiveDetector ...@@ -165,7 +153,6 @@ class CORE_EXPORT InteractiveDetector
base::TimeDelta total_input_delay; base::TimeDelta total_input_delay;
base::TimeDelta total_adjusted_input_delay; base::TimeDelta total_adjusted_input_delay;
uint64_t num_input_events; uint64_t num_input_events;
bool first_meaningful_paint_invalidated = false;
} page_event_times_; } page_event_times_;
struct VisibilityChangeEvent { struct VisibilityChangeEvent {
......
...@@ -99,12 +99,6 @@ void PaintTiming::SetFirstMeaningfulPaint( ...@@ -99,12 +99,6 @@ void PaintTiming::SetFirstMeaningfulPaint(
"loading,rail,devtools.timeline", "firstMeaningfulPaint", swap_stamp, "loading,rail,devtools.timeline", "firstMeaningfulPaint", swap_stamp,
"frame", ToTraceValue(GetFrame()), "afterUserInput", had_input); "frame", ToTraceValue(GetFrame()), "afterUserInput", had_input);
InteractiveDetector* interactive_detector(
InteractiveDetector::From(*GetSupplementable()));
if (interactive_detector) {
interactive_detector->OnFirstMeaningfulPaintDetected(swap_stamp, had_input);
}
// Notify FMP for UMA only if there's no user input before FMP, so that layout // Notify FMP for UMA only if there's no user input before FMP, so that layout
// changes caused by user interactions wouldn't be considered as FMP. // changes caused by user interactions wouldn't be considered as FMP.
if (had_input == FirstMeaningfulPaintDetector::kNoUserInput) { if (had_input == FirstMeaningfulPaintDetector::kNoUserInput) {
...@@ -246,6 +240,11 @@ void PaintTiming::SetFirstContentfulPaintSwap(base::TimeTicks stamp) { ...@@ -246,6 +240,11 @@ void PaintTiming::SetFirstContentfulPaintSwap(base::TimeTicks stamp) {
GetFrame()->Loader().Progress().DidFirstContentfulPaint(); GetFrame()->Loader().Progress().DidFirstContentfulPaint();
NotifyPaintTimingChanged(); NotifyPaintTimingChanged();
fmp_detector_->NotifyFirstContentfulPaint(first_contentful_paint_swap_); fmp_detector_->NotifyFirstContentfulPaint(first_contentful_paint_swap_);
InteractiveDetector* interactive_detector =
InteractiveDetector::From(*GetSupplementable());
if (interactive_detector) {
interactive_detector->OnFirstContentfulPaint(first_contentful_paint_swap_);
}
} }
void PaintTiming::SetFirstImagePaintSwap(base::TimeTicks stamp) { void PaintTiming::SetFirstImagePaintSwap(base::TimeTicks stamp) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment