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

Unified Diff: chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc

Issue 2901383002: Buffer cross frame paint timing updates. (Closed)
Patch Set: address comment Created 3 years, 7 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: chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
index f5e4ec5fa3fa7f7dcb2b509d043f36ea34fb9144..0f47b82769613f7f74b6f2e46a311300ba03f04b 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_update_dispatcher.cc
@@ -25,6 +25,10 @@ namespace internal {
const char kPageLoadTimingStatus[] = "PageLoad.Internal.PageLoadTimingStatus";
const char kPageLoadTimingDispatchStatus[] =
"PageLoad.Internal.PageLoadTimingStatus.AtTimingCallbackDispatch";
+const char kHistogramOutOfOrderTiming[] =
+ "PageLoad.Internal.OutOfOrderInterFrameTiming";
+const char kHistogramOutOfOrderTimingBuffered[] =
+ "PageLoad.Internal.OutOfOrderInterFrameTiming.AfterBuffering";
} // namespace internal
@@ -200,10 +204,57 @@ internal::PageLoadTimingStatus IsValidPageLoadTiming(
return internal::VALID;
}
+// If the updated value has an earlier time than the current value, log so we
+// can keep track of how often this happens.
+void LogIfOutOfOrderTiming(const base::Optional<base::TimeDelta>& current,
+ const base::Optional<base::TimeDelta>& update) {
+ if (!current || !update)
+ return;
+
+ if (update < current) {
+ PAGE_LOAD_HISTOGRAM(internal::kHistogramOutOfOrderTimingBuffered,
+ current.value() - update.value());
+ }
+}
+
+// PaintTimingMerger merges paint timing values received from different frames
+// together.
+class PaintTimingMerger {
+ public:
+ explicit PaintTimingMerger(mojom::PaintTiming* target) : target_(target) {}
+
+ // Merge paint timing values from |new_paint_timing| into the target
+ // PaintTiming.
+ void Merge(base::TimeDelta navigation_start_offset,
+ const mojom::PaintTiming& new_paint_timing,
+ bool is_main_frame);
+
+ // Whether we merged a new value, for a paint timing field we didn't
+ // previously have a value for in the target PaintTiming.
+ bool did_merge_new_timing_value() const {
+ return did_merge_new_timing_value_;
+ }
+
+ private:
+ void MaybeUpdateTimeDelta(
+ base::Optional<base::TimeDelta>* inout_existing_value,
+ base::TimeDelta navigation_start_offset,
+ const base::Optional<base::TimeDelta>& optional_candidate_new_value);
+
+ // The target PaintTiming we are merging values into.
+ mojom::PaintTiming* const target_;
+
+ // Whether we merged a new value, for a paint timing field we didn't
+ // previously have a value for in |target_|.
+ bool did_merge_new_timing_value_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintTimingMerger);
+};
+
// Updates *|inout_existing_value| with |optional_candidate_new_value|, if
// either *|inout_existing_value| isn't set, or |optional_candidate_new_value| <
// |inout_existing_value|.
-void MaybeUpdateTimeDelta(
+void PaintTimingMerger::MaybeUpdateTimeDelta(
base::Optional<base::TimeDelta>* inout_existing_value,
base::TimeDelta navigation_start_offset,
const base::Optional<base::TimeDelta>& optional_candidate_new_value) {
@@ -228,13 +279,33 @@ void MaybeUpdateTimeDelta(
// occasionally, as inter-frame updates can arrive out of order. Record a
// histogram to track how frequently it happens, along with the magnitude
// of the delta.
- PAGE_LOAD_HISTOGRAM("PageLoad.Internal.OutOfOrderInterFrameTiming",
+ PAGE_LOAD_HISTOGRAM(internal::kHistogramOutOfOrderTiming,
inout_existing_value->value() - candidate_new_value);
+ } else {
+ did_merge_new_timing_value_ = true;
}
*inout_existing_value = candidate_new_value;
}
+void PaintTimingMerger::Merge(base::TimeDelta navigation_start_offset,
+ const mojom::PaintTiming& new_paint_timing,
+ bool is_main_frame) {
+ MaybeUpdateTimeDelta(&target_->first_paint, navigation_start_offset,
+ new_paint_timing.first_paint);
+ MaybeUpdateTimeDelta(&target_->first_text_paint, navigation_start_offset,
+ new_paint_timing.first_text_paint);
+ MaybeUpdateTimeDelta(&target_->first_image_paint, navigation_start_offset,
+ new_paint_timing.first_image_paint);
+ MaybeUpdateTimeDelta(&target_->first_contentful_paint,
+ navigation_start_offset,
+ new_paint_timing.first_contentful_paint);
+ if (is_main_frame) {
+ // First meaningful paint is only tracked in the main frame.
+ target_->first_meaningful_paint = new_paint_timing.first_meaningful_paint;
+ }
+}
+
} // namespace
PageLoadMetricsUpdateDispatcher::PageLoadMetricsUpdateDispatcher(
@@ -243,13 +314,24 @@ PageLoadMetricsUpdateDispatcher::PageLoadMetricsUpdateDispatcher(
PageLoadMetricsEmbedderInterface* embedder_interface)
: client_(client),
embedder_interface_(embedder_interface),
+ timer_(embedder_interface->CreateTimer()),
navigation_start_(navigation_handle->NavigationStart()),
current_merged_page_timing_(CreatePageLoadTiming()),
pending_merged_page_timing_(CreatePageLoadTiming()),
main_frame_metadata_(mojom::PageLoadMetadata::New()),
subframe_metadata_(mojom::PageLoadMetadata::New()) {}
-PageLoadMetricsUpdateDispatcher::~PageLoadMetricsUpdateDispatcher() {}
+PageLoadMetricsUpdateDispatcher::~PageLoadMetricsUpdateDispatcher() {
+ ShutDown();
+}
+
+void PageLoadMetricsUpdateDispatcher::ShutDown() {
+ if (timer_ && timer_->IsRunning()) {
+ timer_->Stop();
+ DispatchTimingUpdates();
+ }
+ timer_ = nullptr;
+}
void PageLoadMetricsUpdateDispatcher::UpdateMetrics(
content::RenderFrameHost* render_frame_host,
@@ -303,32 +385,11 @@ void PageLoadMetricsUpdateDispatcher::UpdateSubFrameTiming(
client_->OnSubFrameTimingChanged(new_timing);
base::TimeDelta navigation_start_offset = it->second;
- MergePaintTiming(navigation_start_offset, *(new_timing.paint_timing),
- false /* is_main_frame */);
+ PaintTimingMerger merger(pending_merged_page_timing_->paint_timing.get());
+ merger.Merge(navigation_start_offset, *new_timing.paint_timing,
+ false /* is_main_frame */);
- DispatchTimingUpdates();
-}
-
-void PageLoadMetricsUpdateDispatcher::MergePaintTiming(
- base::TimeDelta navigation_start_offset,
- const mojom::PaintTiming& new_paint_timing,
- bool is_main_frame) {
- MaybeUpdateTimeDelta(&pending_merged_page_timing_->paint_timing->first_paint,
- navigation_start_offset, new_paint_timing.first_paint);
- MaybeUpdateTimeDelta(
- &pending_merged_page_timing_->paint_timing->first_text_paint,
- navigation_start_offset, new_paint_timing.first_text_paint);
- MaybeUpdateTimeDelta(
- &pending_merged_page_timing_->paint_timing->first_image_paint,
- navigation_start_offset, new_paint_timing.first_image_paint);
- MaybeUpdateTimeDelta(
- &pending_merged_page_timing_->paint_timing->first_contentful_paint,
- navigation_start_offset, new_paint_timing.first_contentful_paint);
- if (is_main_frame) {
- // first meaningful paint is only tracked in the main frame.
- pending_merged_page_timing_->paint_timing->first_meaningful_paint =
- new_paint_timing.first_meaningful_paint;
- }
+ MaybeDispatchTimingUpdates(merger.did_merge_new_timing_value());
}
void PageLoadMetricsUpdateDispatcher::UpdateSubFrameMetadata(
@@ -374,10 +435,12 @@ void PageLoadMetricsUpdateDispatcher::UpdateMainFrameTiming(
// observed |paint_timing|, which is tracked across all frames in the page.
pending_merged_page_timing_ = new_timing.Clone();
pending_merged_page_timing_->paint_timing = std::move(last_paint_timing);
- MergePaintTiming(base::TimeDelta(), *new_timing.paint_timing,
- true /* is_main_frame */);
- DispatchTimingUpdates();
+ PaintTimingMerger merger(pending_merged_page_timing_->paint_timing.get());
+ merger.Merge(base::TimeDelta(), *new_timing.paint_timing,
+ true /* is_main_frame */);
+
+ MaybeDispatchTimingUpdates(merger.did_merge_new_timing_value());
}
void PageLoadMetricsUpdateDispatcher::UpdateMainFrameMetadata(
@@ -398,7 +461,24 @@ void PageLoadMetricsUpdateDispatcher::UpdateMainFrameMetadata(
client_->OnMainFrameMetadataChanged();
}
+void PageLoadMetricsUpdateDispatcher::MaybeDispatchTimingUpdates(
+ bool did_merge_new_timing_value) {
+ // If we merged a new timing value, then we should buffer updates for
+ // |kBufferTimerDelayMillis|, to allow for any other out of order timings to
+ // arrive before we dispatch the minimum observed timings to observers.
+ if (did_merge_new_timing_value) {
+ timer_->Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(kBufferTimerDelayMillis),
+ base::Bind(&PageLoadMetricsUpdateDispatcher::DispatchTimingUpdates,
+ base::Unretained(this)));
+ } else if (!timer_->IsRunning()) {
+ DispatchTimingUpdates();
+ }
+}
+
void PageLoadMetricsUpdateDispatcher::DispatchTimingUpdates() {
+ DCHECK(!timer_->IsRunning());
+
if (pending_merged_page_timing_->paint_timing->first_paint) {
if (!pending_merged_page_timing_->parse_timing->parse_start ||
!pending_merged_page_timing_->document_timing->first_layout) {
@@ -418,6 +498,19 @@ void PageLoadMetricsUpdateDispatcher::DispatchTimingUpdates() {
if (current_merged_page_timing_->Equals(*pending_merged_page_timing_))
return;
+
+ LogIfOutOfOrderTiming(current_merged_page_timing_->paint_timing->first_paint,
+ pending_merged_page_timing_->paint_timing->first_paint);
+ LogIfOutOfOrderTiming(
+ current_merged_page_timing_->paint_timing->first_text_paint,
+ pending_merged_page_timing_->paint_timing->first_text_paint);
+ LogIfOutOfOrderTiming(
+ current_merged_page_timing_->paint_timing->first_image_paint,
+ pending_merged_page_timing_->paint_timing->first_image_paint);
+ LogIfOutOfOrderTiming(
+ current_merged_page_timing_->paint_timing->first_contentful_paint,
+ pending_merged_page_timing_->paint_timing->first_contentful_paint);
+
current_merged_page_timing_ = pending_merged_page_timing_->Clone();
internal::PageLoadTimingStatus status =

Powered by Google App Engine
This is Rietveld 408576698