0

Allocate SharedMemoryMapping for DroppedFrames UKM.

This CL is part of the investigation into replacing
DroppedFrameCounter UKMs with FrameSequenceMetrics.
Details about DFC metrics and why they are redundant
can be found in go/chrome-cc-metrics-refactor.

New Metric Doc: go/chrome-graphics-fsm-as-ukm

Why is this CL so complicated? Approach explained
here: go/chrome-cc-pdf4-as-ukm-why

Bug: 338977417, 395868899
Change-Id: I2a4f222088881f8e58b61b6d55144f91466f808a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6187722
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Ian Clelland <iclelland@chromium.org>
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Commit-Queue: Stacy Gaikovaia <gaiko@google.com>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1422117}
This commit is contained in:
Stacy Gaikovaia
2025-02-19 11:48:01 -08:00
committed by Chromium LUCI CQ
parent 9f07f94af1
commit b3deb703f9
49 changed files with 323 additions and 115 deletions

@ -221,6 +221,8 @@ cc_component("cc") {
"metrics/submit_info.h", "metrics/submit_info.h",
"metrics/total_frame_counter.cc", "metrics/total_frame_counter.cc",
"metrics/total_frame_counter.h", "metrics/total_frame_counter.h",
"metrics/ukm_dropped_frames_data.cc",
"metrics/ukm_dropped_frames_data.h",
"metrics/ukm_manager.cc", "metrics/ukm_manager.cc",
"metrics/ukm_manager.h", "metrics/ukm_manager.h",
"metrics/ukm_smoothness_data.cc", "metrics/ukm_smoothness_data.cc",

@ -15,6 +15,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h" #include "base/trace_event/traced_value.h"
#include "cc/metrics/dropped_frame_counter.h"
#include "cc/metrics/frame_info.h" #include "cc/metrics/frame_info.h"
#include "cc/metrics/frame_sequence_tracker.h" #include "cc/metrics/frame_sequence_tracker.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/frame_sinks/begin_frame_args.h"
@ -277,7 +278,7 @@ void FrameSequenceMetrics::AdoptTrace(FrameSequenceMetrics* adopt_from) {
adopt_from->trace_data_.trace_id = 0u; adopt_from->trace_data_.trace_id = 0u;
} }
void FrameSequenceMetrics::ReportMetrics() { int FrameSequenceMetrics::ReportMetrics() {
// Terminates |trace_data_| for all types of FrameSequenceTracker. // Terminates |trace_data_| for all types of FrameSequenceTracker.
trace_data_.Terminate(v3_, v4_, GetEffectiveThread()); trace_data_.Terminate(v3_, v4_, GetEffectiveThread());
@ -301,7 +302,7 @@ void FrameSequenceMetrics::ReportMetrics() {
v4_.frames_checkerboarded = 0u; v4_.frames_checkerboarded = 0u;
v4_.frames_checkerboarded_need_raster = 0u; v4_.frames_checkerboarded_need_raster = 0u;
v4_.frames_checkerboarded_need_record = 0u; v4_.frames_checkerboarded_need_record = 0u;
return; return -1;
} }
const auto thread_type = GetEffectiveThread(); const auto thread_type = GetEffectiveThread();
@ -457,6 +458,7 @@ void FrameSequenceMetrics::ReportMetrics() {
base::LinearHistogram::FactoryGet( base::LinearHistogram::FactoryGet(
GetJankV3HistogramName(type_, thread_name), 1, 100, 101, GetJankV3HistogramName(type_, thread_name), 1, 100, 101,
base::HistogramBase::kUmaTargetedHistogramFlag)); base::HistogramBase::kUmaTargetedHistogramFlag));
v3_.frames_expected = 0u; v3_.frames_expected = 0u;
v3_.frames_dropped = 0u; v3_.frames_dropped = 0u;
v3_.frames_missing_content = 0u; v3_.frames_missing_content = 0u;
@ -465,7 +467,11 @@ void FrameSequenceMetrics::ReportMetrics() {
v4_.frames_checkerboarded = 0u; v4_.frames_checkerboarded = 0u;
v4_.frames_checkerboarded_need_raster = 0u; v4_.frames_checkerboarded_need_raster = 0u;
v4_.frames_checkerboarded_need_record = 0u; v4_.frames_checkerboarded_need_record = 0u;
// Return PDF4 to write to UKMs.
return percent_dropped_v4;
} }
return -1;
} }
FrameSequenceMetrics::TraceData::TraceData(FrameSequenceMetrics* m) FrameSequenceMetrics::TraceData::TraceData(FrameSequenceMetrics* m)

@ -13,6 +13,7 @@
#include "base/check.h" #include "base/check.h"
#include "base/functional/callback.h" #include "base/functional/callback.h"
#include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/trace_event/traced_value.h" #include "base/trace_event/traced_value.h"
#include "cc/cc_export.h" #include "cc/cc_export.h"
@ -121,7 +122,8 @@ class CC_EXPORT FrameSequenceMetrics {
bool HasEnoughDataForReporting() const; bool HasEnoughDataForReporting() const;
bool HasDataLeftForReporting() const; bool HasDataLeftForReporting() const;
// Report related metrics: throughput, checkboarding... // Report related metrics: throughput, checkboarding...
void ReportMetrics(); // Returns PercentDroppedFrames4.AllSequences metric.
int ReportMetrics();
void AddSortedFrame(const viz::BeginFrameArgs& args, void AddSortedFrame(const viz::BeginFrameArgs& args,
const FrameInfo& frame_info); const FrameInfo& frame_info);

@ -9,8 +9,13 @@
#include "base/containers/contains.h" #include "base/containers/contains.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/writable_shared_memory_region.h"
#include "cc/metrics/compositor_frame_reporting_controller.h" #include "cc/metrics/compositor_frame_reporting_controller.h"
#include "cc/metrics/frame_sequence_metrics.h"
#include "cc/metrics/frame_sequence_tracker.h" #include "cc/metrics/frame_sequence_tracker.h"
#include "cc/metrics/ukm_dropped_frames_data.h"
#include "cc/metrics/ukm_smoothness_data.h"
namespace cc { namespace cc {
@ -262,8 +267,10 @@ void FrameSequenceTrackerCollection::DestroyTrackers() {
accumulated_metrics_.erase(key); accumulated_metrics_.erase(key);
} }
if (metrics->HasEnoughDataForReporting()) if (metrics->HasEnoughDataForReporting()) {
metrics->ReportMetrics(); metrics->ReportMetrics();
// TODO(crbug.com/395868899): Write PDF4 metric here
}
if (metrics->HasDataLeftForReporting()) if (metrics->HasDataLeftForReporting())
accumulated_metrics_[key] = std::move(metrics); accumulated_metrics_[key] = std::move(metrics);
} }
@ -354,4 +361,9 @@ void FrameSequenceTrackerCollection::AddSortedFrame(
DestroyTrackers(); DestroyTrackers();
} }
void FrameSequenceTrackerCollection::SetUkmDroppedFramesDestination(
UkmDroppedFramesDataShared* dropped_frames_data) {
ukm_dropped_frames_data_ = dropped_frames_data;
}
} // namespace cc } // namespace cc

@ -12,8 +12,11 @@
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "base/functional/callback.h" #include "base/functional/callback.h"
#include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr.h"
#include "base/memory/shared_memory_mapping.h"
#include "cc/cc_export.h" #include "cc/cc_export.h"
#include "cc/metrics/dropped_frame_counter.h"
#include "cc/metrics/frame_sequence_metrics.h" #include "cc/metrics/frame_sequence_metrics.h"
#include "cc/metrics/ukm_dropped_frames_data.h"
namespace viz { namespace viz {
struct BeginFrameArgs; struct BeginFrameArgs;
@ -22,7 +25,6 @@ struct BeginFrameArgs;
namespace cc { namespace cc {
class FrameSequenceTracker; class FrameSequenceTracker;
class CompositorFrameReportingController; class CompositorFrameReportingController;
class UkmManager;
// Map of kCustom tracker results keyed by a sequence id. // Map of kCustom tracker results keyed by a sequence id.
using CustomTrackerResults = using CustomTrackerResults =
@ -88,8 +90,6 @@ class CC_EXPORT FrameSequenceTrackerCollection {
FrameSequenceTracker* GetRemovalTrackerForTesting( FrameSequenceTracker* GetRemovalTrackerForTesting(
FrameSequenceTrackerType type); FrameSequenceTrackerType type);
void SetUkmManager(UkmManager* manager);
using NotifyCustomerTrackerResutlsCallback = using NotifyCustomerTrackerResutlsCallback =
base::RepeatingCallback<void(const CustomTrackerResults&)>; base::RepeatingCallback<void(const CustomTrackerResults&)>;
void set_custom_tracker_results_added_callback( void set_custom_tracker_results_added_callback(
@ -100,6 +100,10 @@ class CC_EXPORT FrameSequenceTrackerCollection {
void AddSortedFrame(const viz::BeginFrameArgs& args, void AddSortedFrame(const viz::BeginFrameArgs& args,
const FrameInfo& frame_info); const FrameInfo& frame_info);
// Registers the shared memory location for PDF4 UKMs.
void SetUkmDroppedFramesDestination(
UkmDroppedFramesDataShared* dropped_frames_data);
private: private:
friend class FrameSequenceTrackerTest; friend class FrameSequenceTrackerTest;
@ -150,6 +154,9 @@ class CC_EXPORT FrameSequenceTrackerCollection {
size_t main_thread_driving_smoothness_ = 0; size_t main_thread_driving_smoothness_ = 0;
size_t compositor_thread_driving_smoothness_ = 0; size_t compositor_thread_driving_smoothness_ = 0;
size_t raster_thread_driving_smoothness_ = 0; size_t raster_thread_driving_smoothness_ = 0;
// Pointer to shared memory map for PDF4 UKMs
raw_ptr<UkmDroppedFramesDataShared> ukm_dropped_frames_data_ = nullptr;
}; };
} // namespace cc } // namespace cc

@ -0,0 +1,11 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/metrics/ukm_dropped_frames_data.h"
namespace cc {
UkmDroppedFramesData::UkmDroppedFramesData() = default;
} // namespace cc

@ -0,0 +1,26 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_METRICS_UKM_DROPPED_FRAMES_DATA_H_
#define CC_METRICS_UKM_DROPPED_FRAMES_DATA_H_
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "cc/metrics/shared_metrics_buffer.h"
namespace cc {
// PercentDroppedFrames4 UKM metric
// exported from frame_sequence_metrics.cc
struct CC_EXPORT UkmDroppedFramesData {
UkmDroppedFramesData();
double percent_dropped_frames = 0.0;
};
using UkmDroppedFramesDataShared = SharedMetricsBuffer<UkmDroppedFramesData>;
} // namespace cc
#endif // CC_METRICS_UKM_DROPPED_FRAMES_DATA_H_

@ -62,6 +62,8 @@ class FakeProxy : public Proxy {
void SetSourceURL(ukm::SourceId source_id, const GURL& url) override {} void SetSourceURL(ukm::SourceId source_id, const GURL& url) override {}
void SetUkmSmoothnessDestination( void SetUkmSmoothnessDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data) override {} base::WritableSharedMemoryMapping ukm_smoothness_data) override {}
void SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data) override {}
void SetRenderFrameObserver( void SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer) override {} std::unique_ptr<RenderFrameMetadataObserver> observer) override {}
void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time, void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time,

@ -48,6 +48,7 @@
#include "cc/layers/heads_up_display_layer_impl.h" #include "cc/layers/heads_up_display_layer_impl.h"
#include "cc/layers/layer.h" #include "cc/layers/layer.h"
#include "cc/layers/painted_scrollbar_layer.h" #include "cc/layers/painted_scrollbar_layer.h"
#include "cc/metrics/ukm_dropped_frames_data.h"
#include "cc/metrics/ukm_manager.h" #include "cc/metrics/ukm_manager.h"
#include "cc/metrics/ukm_smoothness_data.h" #include "cc/metrics/ukm_smoothness_data.h"
#include "cc/paint/paint_worklet_layer_painter.h" #include "cc/paint/paint_worklet_layer_painter.h"
@ -1986,6 +1987,20 @@ LayerTreeHost::CreateSharedMemoryForSmoothnessUkm() {
return std::move(ukm_smoothness_mapping.region); return std::move(ukm_smoothness_mapping.region);
} }
base::ReadOnlySharedMemoryRegion
LayerTreeHost::CreateSharedMemoryForDroppedFramesUkm() {
DCHECK(IsMainThread());
const auto size = sizeof(UkmDroppedFramesDataShared);
auto ukm_dropped_frames_mapping =
base::ReadOnlySharedMemoryRegion::Create(size);
if (!ukm_dropped_frames_mapping.IsValid()) {
return {};
}
proxy_->SetUkmDroppedFramesDestination(
std::move(ukm_dropped_frames_mapping.mapping));
return std::move(ukm_dropped_frames_mapping.region);
}
void LayerTreeHost::SetRenderFrameObserver( void LayerTreeHost::SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer) { std::unique_ptr<RenderFrameMetadataObserver> observer) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());

@ -914,6 +914,7 @@ class CC_EXPORT LayerTreeHost : public MutatorHostClient {
void SetSourceURL(ukm::SourceId source_id, const GURL& url); void SetSourceURL(ukm::SourceId source_id, const GURL& url);
base::ReadOnlySharedMemoryRegion CreateSharedMemoryForSmoothnessUkm(); base::ReadOnlySharedMemoryRegion CreateSharedMemoryForSmoothnessUkm();
base::ReadOnlySharedMemoryRegion CreateSharedMemoryForDroppedFramesUkm();
void SetRenderFrameObserver( void SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer); std::unique_ptr<RenderFrameMetadataObserver> observer);

@ -75,6 +75,7 @@
#include "cc/metrics/frame_sequence_metrics.h" #include "cc/metrics/frame_sequence_metrics.h"
#include "cc/metrics/lcd_text_metrics_reporter.h" #include "cc/metrics/lcd_text_metrics_reporter.h"
#include "cc/metrics/submit_info.h" #include "cc/metrics/submit_info.h"
#include "cc/metrics/ukm_dropped_frames_data.h"
#include "cc/metrics/ukm_smoothness_data.h" #include "cc/metrics/ukm_smoothness_data.h"
#include "cc/paint/display_item_list.h" #include "cc/paint/display_item_list.h"
#include "cc/paint/paint_worklet_job.h" #include "cc/paint/paint_worklet_job.h"
@ -5774,6 +5775,13 @@ void LayerTreeHostImpl::SetUkmSmoothnessDestination(
ukm_smoothness_mapping_ = std::move(ukm_smoothness_data); ukm_smoothness_mapping_ = std::move(ukm_smoothness_data);
} }
void LayerTreeHostImpl::SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data) {
frame_trackers_.SetUkmDroppedFramesDestination(
ukm_dropped_frames_data.GetMemoryAs<UkmDroppedFramesDataShared>());
ukm_dropped_frames_mapping_ = std::move(ukm_dropped_frames_data);
}
void LayerTreeHostImpl::NotifyDidPresentCompositorFrameOnImplThread( void LayerTreeHostImpl::NotifyDidPresentCompositorFrameOnImplThread(
uint32_t frame_token, uint32_t frame_token,
std::vector<PresentationTimeCallbackBuffer::SuccessfulCallback> callbacks, std::vector<PresentationTimeCallbackBuffer::SuccessfulCallback> callbacks,

@ -799,6 +799,8 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
void SetUkmSmoothnessDestination( void SetUkmSmoothnessDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data); base::WritableSharedMemoryMapping ukm_smoothness_data);
void SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data);
// Notifies FrameTrackers, impl side callbacks that the compsitor frame // Notifies FrameTrackers, impl side callbacks that the compsitor frame
// was presented. // was presented.
@ -1096,6 +1098,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
std::unique_ptr<PageScaleAnimation> page_scale_animation_; std::unique_ptr<PageScaleAnimation> page_scale_animation_;
base::WritableSharedMemoryMapping ukm_smoothness_mapping_; base::WritableSharedMemoryMapping ukm_smoothness_mapping_;
base::WritableSharedMemoryMapping ukm_dropped_frames_mapping_;
TotalFrameCounter total_frame_counter_; TotalFrameCounter total_frame_counter_;
// `dropped_frame_counter_` holds a pointer `to ukm_smoothness_mapping_` so // `dropped_frame_counter_` holds a pointer `to ukm_smoothness_mapping_` so

@ -9695,6 +9695,8 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest {
void SetupTree() override { void SetupTree() override {
LayerTreeTest::SetupTree(); LayerTreeTest::SetupTree();
shmem_region_ = layer_tree_host()->CreateSharedMemoryForSmoothnessUkm(); shmem_region_ = layer_tree_host()->CreateSharedMemoryForSmoothnessUkm();
shmem_region_dropped_frames_ =
layer_tree_host()->CreateSharedMemoryForDroppedFramesUkm();
} }
void BeginTest() override { void BeginTest() override {
@ -9710,6 +9712,9 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest {
// It is not always possible to guarantee an exact number of dropped frames. // It is not always possible to guarantee an exact number of dropped frames.
// So validate that there are non-zero dropped frames. // So validate that there are non-zero dropped frames.
EXPECT_GT(smoothness->data.avg_smoothness, 0); EXPECT_GT(smoothness->data.avg_smoothness, 0);
ASSERT_TRUE(shmem_region_dropped_frames_.IsValid());
// TODO(crbug.com/395868899): Test that values are exported here.
} }
void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl, void WillBeginImplFrameOnThread(LayerTreeHostImpl* host_impl,
@ -9744,6 +9749,7 @@ class LayerTreeHostUkmSmoothnessMetric : public LayerTreeTest {
bool fcp_sent_ = false; bool fcp_sent_ = false;
viz::BeginFrameArgs last_args_; viz::BeginFrameArgs last_args_;
base::ReadOnlySharedMemoryRegion shmem_region_; base::ReadOnlySharedMemoryRegion shmem_region_;
base::ReadOnlySharedMemoryRegion shmem_region_dropped_frames_;
}; };
MULTI_THREAD_TEST_F(LayerTreeHostUkmSmoothnessMetric); MULTI_THREAD_TEST_F(LayerTreeHostUkmSmoothnessMetric);

@ -8,12 +8,14 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "base/memory/shared_memory_mapping.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/types/optional_ref.h" #include "base/types/optional_ref.h"
#include "cc/cc_export.h" #include "cc/cc_export.h"
#include "cc/input/browser_controls_offset_tag_modifications.h" #include "cc/input/browser_controls_offset_tag_modifications.h"
#include "cc/input/browser_controls_state.h" #include "cc/input/browser_controls_state.h"
#include "cc/paint/draw_image.h"
#include "cc/trees/paint_holding_commit_trigger.h" #include "cc/trees/paint_holding_commit_trigger.h"
#include "cc/trees/paint_holding_reason.h" #include "cc/trees/paint_holding_reason.h"
#include "cc/trees/task_runner_provider.h" #include "cc/trees/task_runner_provider.h"
@ -115,6 +117,9 @@ class CC_EXPORT Proxy {
virtual void SetUkmSmoothnessDestination( virtual void SetUkmSmoothnessDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data) = 0; base::WritableSharedMemoryMapping ukm_smoothness_data) = 0;
virtual void SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data) = 0;
virtual void SetRenderFrameObserver( virtual void SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer) = 0; std::unique_ptr<RenderFrameMetadataObserver> observer) = 0;

@ -1013,6 +1013,13 @@ void ProxyImpl::SetUkmSmoothnessDestination(
host_impl_->SetUkmSmoothnessDestination(std::move(ukm_smoothness_data)); host_impl_->SetUkmSmoothnessDestination(std::move(ukm_smoothness_data));
} }
void ProxyImpl::SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data) {
DCHECK(IsImplThread());
host_impl_->SetUkmDroppedFramesDestination(
std::move(ukm_dropped_frames_data));
}
void ProxyImpl::ClearHistory() { void ProxyImpl::ClearHistory() {
DCHECK(IsImplThread()); DCHECK(IsImplThread());
scheduler_->ClearHistory(); scheduler_->ClearHistory();

@ -104,6 +104,8 @@ class CC_EXPORT ProxyImpl : public LayerTreeHostImplClient,
void SetSourceURL(ukm::SourceId source_id, const GURL& url); void SetSourceURL(ukm::SourceId source_id, const GURL& url);
void SetUkmSmoothnessDestination( void SetUkmSmoothnessDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data); base::WritableSharedMemoryMapping ukm_smoothness_data);
void SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data);
void SetRenderFrameObserver( void SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer); std::unique_ptr<RenderFrameMetadataObserver> observer);
void DetachInputDelegateAndRenderFrameObserver( void DetachInputDelegateAndRenderFrameObserver(

@ -916,6 +916,15 @@ void ProxyMain::SetUkmSmoothnessDestination(
std::move(ukm_smoothness_data))); std::move(ukm_smoothness_data)));
} }
void ProxyMain::SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data) {
DCHECK(IsMainThread());
ImplThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&ProxyImpl::SetUkmDroppedFramesDestination,
base::Unretained(proxy_impl_.get()),
std::move(ukm_dropped_frames_data)));
}
void ProxyMain::SetRenderFrameObserver( void ProxyMain::SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer) { std::unique_ptr<RenderFrameMetadataObserver> observer) {
ImplThreadTaskRunner()->PostTask( ImplThreadTaskRunner()->PostTask(

@ -129,6 +129,8 @@ class CC_EXPORT ProxyMain : public Proxy {
void SetSourceURL(ukm::SourceId source_id, const GURL& url) override; void SetSourceURL(ukm::SourceId source_id, const GURL& url) override;
void SetUkmSmoothnessDestination( void SetUkmSmoothnessDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data) override; base::WritableSharedMemoryMapping ukm_smoothness_data) override;
void SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_dropped_frames_data) override;
void SetRenderFrameObserver( void SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer) override; std::unique_ptr<RenderFrameMetadataObserver> observer) override;
void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time, void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time,

@ -944,6 +944,11 @@ void SingleThreadProxy::SetUkmSmoothnessDestination(
DCHECK(task_runner_provider_->IsMainThread()); DCHECK(task_runner_provider_->IsMainThread());
} }
void SingleThreadProxy::SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data) {
DCHECK(task_runner_provider_->IsMainThread());
}
void SingleThreadProxy::ClearHistory() { void SingleThreadProxy::ClearHistory() {
DCHECK(task_runner_provider_->IsImplThread()); DCHECK(task_runner_provider_->IsImplThread());
if (scheduler_on_impl_thread_) if (scheduler_on_impl_thread_)

@ -83,6 +83,8 @@ class CC_EXPORT SingleThreadProxy : public Proxy,
void SetSourceURL(ukm::SourceId source_id, const GURL& url) override; void SetSourceURL(ukm::SourceId source_id, const GURL& url) override;
void SetUkmSmoothnessDestination( void SetUkmSmoothnessDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data) override; base::WritableSharedMemoryMapping ukm_smoothness_data) override;
void SetUkmDroppedFramesDestination(
base::WritableSharedMemoryMapping ukm_smoothness_data) override;
void SetRenderFrameObserver( void SetRenderFrameObserver(
std::unique_ptr<RenderFrameMetadataObserver> observer) override; std::unique_ptr<RenderFrameMetadataObserver> observer) override;
void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time, void CompositeImmediatelyForTest(base::TimeTicks frame_begin_time,

@ -24,6 +24,7 @@
#include "base/trace_event/trace_id_helper.h" #include "base/trace_event/trace_id_helper.h"
#include "base/trace_event/typed_macros.h" #include "base/trace_event/typed_macros.h"
#include "cc/base/features.h" #include "cc/base/features.h"
#include "cc/metrics/ukm_dropped_frames_data.h"
#include "cc/metrics/ukm_smoothness_data.h" #include "cc/metrics/ukm_smoothness_data.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h" #include "chrome/browser/content_settings/cookie_settings_factory.h"
@ -426,6 +427,7 @@ UkmPageLoadMetricsObserver::FlushMetricsOnAppEnterBackground(
if (GetDelegate().StartedInForeground()) if (GetDelegate().StartedInForeground())
RecordTimingMetrics(timing); RecordTimingMetrics(timing);
ReportLayoutStability(); ReportLayoutStability();
RecordDroppedFramesMetrics();
RecordSmoothnessMetrics(); RecordSmoothnessMetrics();
RecordResponsivenessMetrics(); RecordResponsivenessMetrics();
// Assume that page ends on this method, as the app could be evicted right // Assume that page ends on this method, as the app could be evicted right
@ -505,6 +507,7 @@ void UkmPageLoadMetricsObserver::OnComplete(
if (GetDelegate().StartedInForeground()) if (GetDelegate().StartedInForeground())
RecordTimingMetrics(timing); RecordTimingMetrics(timing);
ReportLayoutStability(); ReportLayoutStability();
RecordDroppedFramesMetrics();
RecordSmoothnessMetrics(); RecordSmoothnessMetrics();
RecordResponsivenessMetrics(); RecordResponsivenessMetrics();
RecordPageEndMetrics(&timing, current_time, RecordPageEndMetrics(&timing, current_time,
@ -1523,6 +1526,21 @@ void UkmPageLoadMetricsObserver::RecordPageLoadTimestampMetrics(
builder.SetHourOfDay(exploded.hour); builder.SetHourOfDay(exploded.hour);
} }
void UkmPageLoadMetricsObserver::RecordDroppedFramesMetrics() {
auto* dropped_frames =
ukm_dropped_frames_data_.GetMemoryAs<cc::UkmDroppedFramesDataShared>();
if (!dropped_frames) {
return;
}
cc::UkmDroppedFramesData dropped_frames_data;
bool success = dropped_frames->Read(dropped_frames_data);
if (!success) {
return;
}
// TODO(crbug.com/395868899): Read PDF4 metric here.
}
void UkmPageLoadMetricsObserver::RecordSmoothnessMetrics() { void UkmPageLoadMetricsObserver::RecordSmoothnessMetrics() {
auto* smoothness = auto* smoothness =
ukm_smoothness_data_.GetMemoryAs<cc::UkmSmoothnessDataShared>(); ukm_smoothness_data_.GetMemoryAs<cc::UkmSmoothnessDataShared>();
@ -1774,9 +1792,11 @@ void UkmPageLoadMetricsObserver::OnTimingUpdate(
} }
} }
void UkmPageLoadMetricsObserver::SetUpSharedMemoryForSmoothness( void UkmPageLoadMetricsObserver::SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& shared_memory) { const base::ReadOnlySharedMemoryRegion& smoothness_memory,
ukm_smoothness_data_ = shared_memory.Map(); const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) {
ukm_smoothness_data_ = smoothness_memory.Map();
ukm_dropped_frames_data_ = dropped_frames_memory.Map();
} }
void UkmPageLoadMetricsObserver::OnCpuTimingUpdate( void UkmPageLoadMetricsObserver::OnCpuTimingUpdate(

@ -111,8 +111,9 @@ class UkmPageLoadMetricsObserver
content::RenderFrameHost* subframe_rfh, content::RenderFrameHost* subframe_rfh,
const page_load_metrics::mojom::PageLoadTiming& timing) override; const page_load_metrics::mojom::PageLoadTiming& timing) override;
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& shared_memory) override; const base::ReadOnlySharedMemoryRegion& smoothness_memory,
const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) override;
void OnCpuTimingUpdate( void OnCpuTimingUpdate(
content::RenderFrameHost* subframe_rfh, content::RenderFrameHost* subframe_rfh,
@ -187,6 +188,7 @@ class UkmPageLoadMetricsObserver
ukm::builders::PageLoad& builder, ukm::builders::PageLoad& builder,
const page_load_metrics::PageEndReason page_end_reason); const page_load_metrics::PageEndReason page_end_reason);
void RecordDroppedFramesMetrics();
void RecordSmoothnessMetrics(); void RecordSmoothnessMetrics();
void RecordResponsivenessMetrics(); void RecordResponsivenessMetrics();
@ -362,6 +364,7 @@ class UkmPageLoadMetricsObserver
std::optional<net::HttpConnectionInfo> connection_info_; std::optional<net::HttpConnectionInfo> connection_info_;
base::ReadOnlySharedMemoryMapping ukm_smoothness_data_; base::ReadOnlySharedMemoryMapping ukm_smoothness_data_;
base::ReadOnlySharedMemoryMapping ukm_dropped_frames_data_;
// Only true if the page became hidden after the first time it was shown in // Only true if the page became hidden after the first time it was shown in
// the foreground, no matter how it started. // the foreground, no matter how it started.

@ -11,6 +11,7 @@
#include "base/location.h" #include "base/location.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/time/time.h" #include "base/time/time.h"
@ -200,7 +201,7 @@ void MetricsWebContentsObserver::WebContentsDestroyed() {
// access the current WebContents. // access the current WebContents.
primary_page_ = nullptr; primary_page_ = nullptr;
active_pages_.clear(); active_pages_.clear();
ukm_smoothness_data_.clear(); ukm_data_.clear();
provisional_loads_.clear(); provisional_loads_.clear();
aborted_provisional_loads_.clear(); aborted_provisional_loads_.clear();
} }
@ -272,7 +273,7 @@ void MetricsWebContentsObserver::RenderFrameDeleted(
} }
active_pages_.erase(rfh); active_pages_.erase(rfh);
inactive_pages_.erase(rfh); inactive_pages_.erase(rfh);
ukm_smoothness_data_.erase(rfh); ukm_data_.erase(rfh);
} }
void MetricsWebContentsObserver::MediaStartedPlaying( void MetricsWebContentsObserver::MediaStartedPlaying(
@ -825,11 +826,13 @@ void MetricsWebContentsObserver::HandleCommittedNavigationForTrackedLoad(
const bool is_main_frame = const bool is_main_frame =
render_frame_host && render_frame_host->GetParent() == nullptr; render_frame_host && render_frame_host->GetParent() == nullptr;
if (is_main_frame) { if (is_main_frame) {
auto it = ukm_smoothness_data_.find(render_frame_host); auto ukm_it = ukm_data_.find(render_frame_host);
if (it != ukm_smoothness_data_.end()) { if (ukm_it != ukm_data_.end()) {
raw_tracker->metrics_update_dispatcher()->SetUpSharedMemoryForSmoothness( auto& [smoothness_memory, dropped_frames_memory] = ukm_it->second;
render_frame_host, std::move(it->second)); raw_tracker->metrics_update_dispatcher()->SetUpSharedMemoryForUkms(
ukm_smoothness_data_.erase(it); render_frame_host, std::move(smoothness_memory),
std::move(dropped_frames_memory));
ukm_data_.erase(ukm_it);
} }
} }
@ -1254,24 +1257,25 @@ void MetricsWebContentsObserver::AddCustomUserTiming(
OnCustomUserTimingUpdated(render_frame_host, std::move(custom_timing)); OnCustomUserTimingUpdated(render_frame_host, std::move(custom_timing));
} }
void MetricsWebContentsObserver::SetUpSharedMemoryForSmoothness( void MetricsWebContentsObserver::SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) { base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) {
content::RenderFrameHost* render_frame_host = content::RenderFrameHost* render_frame_host =
page_load_metrics_receivers_.GetCurrentTargetFrame(); page_load_metrics_receivers_.GetCurrentTargetFrame();
const bool is_outermost_main_frame = const bool is_outermost_main_frame =
render_frame_host->GetParentOrOuterDocument() == nullptr; render_frame_host->GetParentOrOuterDocument() == nullptr;
if (!is_outermost_main_frame) { if (!is_outermost_main_frame) {
// TODO(crbug.com/40144214): Merge smoothness metrics from OOPIFs and
// FencedFrames with the main-frame. Also need to check if FencedFrames
// send this request correctly.
return; return;
} }
if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) { if (PageLoadTracker* tracker = GetPageLoadTracker(render_frame_host)) {
tracker->metrics_update_dispatcher()->SetUpSharedMemoryForSmoothness( tracker->metrics_update_dispatcher()->SetUpSharedMemoryForUkms(
render_frame_host, std::move(shared_memory)); render_frame_host, std::move(smoothness_memory),
std::move(dropped_frames_memory));
} else { } else {
ukm_smoothness_data_.emplace(render_frame_host, std::move(shared_memory)); ukm_data_.emplace(render_frame_host,
std::make_pair(std::move(smoothness_memory),
std::move(dropped_frames_memory)));
} }
} }

@ -256,8 +256,9 @@ class MetricsWebContentsObserver
void AddCustomUserTiming( void AddCustomUserTiming(
mojom::CustomUserTimingMarkPtr custom_timing) override; mojom::CustomUserTimingMarkPtr custom_timing) override;
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) override; base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) override;
// Common part for UpdateThroughput and OnTimingUpdated. // Common part for UpdateThroughput and OnTimingUpdated.
bool DoesTimingUpdateHaveError(PageLoadTracker* tracker); bool DoesTimingUpdateHaveError(PageLoadTracker* tracker);
@ -392,9 +393,12 @@ class MetricsWebContentsObserver
inactive_pages_; inactive_pages_;
// This is currently set only for the main frame of each page associated with // This is currently set only for the main frame of each page associated with
// the WebContents. // the WebContents. It maps to the shared memory for the smoothness and the
base::flat_map<content::RenderFrameHost*, base::ReadOnlySharedMemoryRegion> // dropped frame count UKMs.
ukm_smoothness_data_; base::flat_map<content::RenderFrameHost*,
std::pair<base::ReadOnlySharedMemoryRegion,
base::ReadOnlySharedMemoryRegion>>
ukm_data_;
std::vector<mojom::CustomUserTimingMarkPtr> page_load_custom_timings_; std::vector<mojom::CustomUserTimingMarkPtr> page_load_custom_timings_;

@ -174,8 +174,9 @@ class AssertPageLoadMetricsObserver final
void OnFeaturesUsageObserved( void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<blink::UseCounterFeature>& features) override {} const std::vector<blink::UseCounterFeature>& features) override {}
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& shared_memory) override {} const base::ReadOnlySharedMemoryRegion& smoothness_memory,
const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) override {}
void OnResourceDataUseObserved( void OnResourceDataUseObserved(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>& const std::vector<page_load_metrics::mojom::ResourceDataUpdatePtr>&

@ -307,12 +307,10 @@ void PageLoadMetricsForwardObserver::OnFeaturesUsageObserved(
parent_observer_->OnFeaturesUsageObserved(rfh, features); parent_observer_->OnFeaturesUsageObserved(rfh, features);
} }
// SetUpSharedMemoryForSmoothness is called only for the outermost page. // SetUpSharedMemoryForUkms is called only for the outermost page.
void PageLoadMetricsForwardObserver::SetUpSharedMemoryForSmoothness( void PageLoadMetricsForwardObserver::SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& shared_memory) { const base::ReadOnlySharedMemoryRegion& smoothness_memory,
// See also MetricsWebContentsObserver::SetUpSharedMemoryForSmoothness and const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) {
// the relevant TODO. Currently, information from OOPIFs and FencedFrames are
// not handled.
// TODO(crbug.com/40895492): Investigate whether this should truly be // TODO(crbug.com/40895492): Investigate whether this should truly be
// unreachable. Note that all NOTREACHED()s were made non-fatal in this file, // unreachable. Note that all NOTREACHED()s were made non-fatal in this file,
// they are not all necessarily hit. // they are not all necessarily hit.

@ -5,6 +5,7 @@
#ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_FORWARD_OBSERVER_H_ #ifndef COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_FORWARD_OBSERVER_H_
#define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_FORWARD_OBSERVER_H_ #define COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_FORWARD_OBSERVER_H_
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer_delegate.h" #include "components/page_load_metrics/browser/page_load_metrics_observer_delegate.h"
#include "components/page_load_metrics/browser/page_load_metrics_observer_interface.h" #include "components/page_load_metrics/browser/page_load_metrics_observer_interface.h"
@ -120,8 +121,9 @@ class PageLoadMetricsForwardObserver final
void OnFeaturesUsageObserved( void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<blink::UseCounterFeature>& features) override; const std::vector<blink::UseCounterFeature>& features) override;
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& shared_memory) override; const base::ReadOnlySharedMemoryRegion& smoothness_memory,
const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) override;
void OnResourceDataUseObserved( void OnResourceDataUseObserved(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) override; const std::vector<mojom::ResourceDataUpdatePtr>& resources) override;

@ -200,8 +200,9 @@ class PageLoadMetricsObserver : public PageLoadMetricsObserverInterface {
void OnFeaturesUsageObserved( void OnFeaturesUsageObserved(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<blink::UseCounterFeature>& features) override {} const std::vector<blink::UseCounterFeature>& features) override {}
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& shared_memory) override {} const base::ReadOnlySharedMemoryRegion& smoothness_memory,
const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) override {}
void OnResourceDataUseObserved( void OnResourceDataUseObserved(
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<mojom::ResourceDataUpdatePtr>& resources) override {} const std::vector<mojom::ResourceDataUpdatePtr>& resources) override {}

@ -450,11 +450,13 @@ class PageLoadMetricsObserverInterface {
content::RenderFrameHost* rfh, content::RenderFrameHost* rfh,
const std::vector<blink::UseCounterFeature>& features) = 0; const std::vector<blink::UseCounterFeature>& features) = 0;
// The smoothness metrics is shared over shared-memory. The observer should // The smoothness and dropped frame count metrics are shared over
// create a mapping (by calling |shared_memory.Map()|) so that they are able // shared-memory. The observer should create a mapping (by calling
// to read from the shared memory. // |shared_memory.Map()|) so that they are able to read from the shared
virtual void SetUpSharedMemoryForSmoothness( // memory.
const base::ReadOnlySharedMemoryRegion& shared_memory) = 0; virtual void SetUpSharedMemoryForUkms(
const base::ReadOnlySharedMemoryRegion& smoothness_memory,
const base::ReadOnlySharedMemoryRegion& dropped_frames_memory) = 0;
// Invoked when there is data use for loading a resource on the page // Invoked when there is data use for loading a resource on the page
// for a given RenderFrameHost. This only contains resources that have had // for a given RenderFrameHost. This only contains resources that have had

@ -508,15 +508,14 @@ void PageLoadMetricsUpdateDispatcher::UpdateFeatures(
client_->UpdateFeaturesUsage(render_frame_host, new_features); client_->UpdateFeaturesUsage(render_frame_host, new_features);
} }
void PageLoadMetricsUpdateDispatcher::SetUpSharedMemoryForSmoothness( void PageLoadMetricsUpdateDispatcher::SetUpSharedMemoryForUkms(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
base::ReadOnlySharedMemoryRegion shared_memory) { base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) {
const bool is_main_frame = client_->IsPageMainFrame(render_frame_host); const bool is_main_frame = client_->IsPageMainFrame(render_frame_host);
if (is_main_frame) { if (is_main_frame) {
client_->SetUpSharedMemoryForSmoothness(std::move(shared_memory)); client_->SetUpSharedMemoryForUkms(std::move(smoothness_memory),
} else { std::move(dropped_frames_memory));
// TODO(crbug.com/40144214): Merge smoothness metrics from OOPIFs with the
// main-frame.
} }
} }

@ -157,8 +157,9 @@ class PageLoadMetricsUpdateDispatcher {
const gfx::Rect& main_frame_viewport_rect) = 0; const gfx::Rect& main_frame_viewport_rect) = 0;
virtual void OnMainFrameImageAdRectsChanged( virtual void OnMainFrameImageAdRectsChanged(
const base::flat_map<int, gfx::Rect>& main_frame_image_ad_rects) = 0; const base::flat_map<int, gfx::Rect>& main_frame_image_ad_rects) = 0;
virtual void SetUpSharedMemoryForSmoothness( virtual void SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) = 0; base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) = 0;
}; };
// The |client| instance must outlive this object. // The |client| instance must outlive this object.
@ -187,9 +188,10 @@ class PageLoadMetricsUpdateDispatcher {
mojom::SoftNavigationMetricsPtr soft_navigation_metrics, mojom::SoftNavigationMetricsPtr soft_navigation_metrics,
internal::PageLoadTrackerPageType page_type); internal::PageLoadTrackerPageType page_type);
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
content::RenderFrameHost* render_frame_host, content::RenderFrameHost* render_frame_host,
base::ReadOnlySharedMemoryRegion shared_memory); base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory);
// This method is only intended to be called for PageLoadFeatures being // This method is only intended to be called for PageLoadFeatures being
// recorded directly from the browser process. Features coming from the // recorded directly from the browser process. Features coming from the

@ -12,6 +12,7 @@
#include "base/check_op.h" #include "base/check_op.h"
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/notreached.h" #include "base/notreached.h"
@ -1123,11 +1124,13 @@ void PageLoadTracker::UpdateFeaturesUsage(
} }
} }
void PageLoadTracker::SetUpSharedMemoryForSmoothness( void PageLoadTracker::SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) { base::ReadOnlySharedMemoryRegion smoothness_memory,
DCHECK(shared_memory.IsValid()); base::ReadOnlySharedMemoryRegion dropped_frames_memory) {
DCHECK(smoothness_memory.IsValid() && dropped_frames_memory.IsValid());
for (auto& observer : observers_) { for (auto& observer : observers_) {
observer->SetUpSharedMemoryForSmoothness(shared_memory); observer->SetUpSharedMemoryForUkms(smoothness_memory,
dropped_frames_memory);
} }
} }

@ -235,8 +235,9 @@ class PageLoadTracker : public PageLoadMetricsUpdateDispatcher::Client,
const gfx::Rect& main_frame_viewport_rect) override; const gfx::Rect& main_frame_viewport_rect) override;
void OnMainFrameImageAdRectsChanged( void OnMainFrameImageAdRectsChanged(
const base::flat_map<int, gfx::Rect>& main_frame_image_ad_rects) override; const base::flat_map<int, gfx::Rect>& main_frame_image_ad_rects) override;
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) override; base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) override;
// PageLoadMetricsObserverDelegate implementation: // PageLoadMetricsObserverDelegate implementation:
content::WebContents* GetWebContents() const override; content::WebContents* GetWebContents() const override;

@ -584,10 +584,12 @@ interface PageLoadMetrics {
SoftNavigationMetrics soft_navigation_metrics); SoftNavigationMetrics soft_navigation_metrics);
// Set up a shared memory used to transfer smoothness data from the renderer // Set up a shared memory used to transfer smoothness data from the renderer
// to the browser. The structure is defined in // to the browser. The structures are defined in
// //cc/metrics/ukm_smoothness_data.h // //cc/metrics/ukm_smoothness_data.h and
SetUpSharedMemoryForSmoothness( // //cc/metrics/ukm_dropped_frames_data.h
mojo_base.mojom.ReadOnlySharedMemoryRegion shared_memory); SetUpSharedMemoryForUkms(
mojo_base.mojom.ReadOnlySharedMemoryRegion smoothness_memory,
mojo_base.mojom.ReadOnlySharedMemoryRegion dropped_frames_memory);
// Called when performance entries are added via `performance.mark()` from the // Called when performance entries are added via `performance.mark()` from the
// outermost main frame in renderer, except for the case when standard // outermost main frame in renderer, except for the case when standard

@ -33,8 +33,9 @@ void FakePageTimingSender::SendTiming(
subresource_load_metrics, soft_navigation_metrics); subresource_load_metrics, soft_navigation_metrics);
} }
void FakePageTimingSender::SetUpSmoothnessReporting( void FakePageTimingSender::SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion shared_memory) {} base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) {}
void FakePageTimingSender::SendCustomUserTiming( void FakePageTimingSender::SendCustomUserTiming(
mojom::CustomUserTimingMarkPtr timing) {} mojom::CustomUserTimingMarkPtr timing) {}

@ -166,8 +166,9 @@ class FakePageTimingSender : public PageTimingSender {
subresource_load_metrics, subresource_load_metrics,
const mojom::SoftNavigationMetricsPtr& soft_navigation_metrics) override; const mojom::SoftNavigationMetricsPtr& soft_navigation_metrics) override;
void SetUpSmoothnessReporting( void SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion shared_memory) override; base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) override;
void SendCustomUserTiming(mojom::CustomUserTimingMarkPtr timing) override; void SendCustomUserTiming(mojom::CustomUserTimingMarkPtr timing) override;

@ -74,11 +74,13 @@ class MojoPageTimingSender : public PageTimingSender {
subresource_load_metrics, soft_navigation_metrics->Clone()); subresource_load_metrics, soft_navigation_metrics->Clone());
} }
void SetUpSmoothnessReporting( void SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion shared_memory) override { base::ReadOnlySharedMemoryRegion shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion shared_memory_dropped_frames) override {
DCHECK(page_load_metrics_); DCHECK(page_load_metrics_);
page_load_metrics_->SetUpSharedMemoryForSmoothness( page_load_metrics_->SetUpSharedMemoryForUkms(
std::move(shared_memory)); std::move(shared_memory_smoothness),
std::move(shared_memory_dropped_frames));
} }
void SendCustomUserTiming(mojom::CustomUserTimingMarkPtr timing) override { void SendCustomUserTiming(mojom::CustomUserTimingMarkPtr timing) override {
@ -419,13 +421,16 @@ void MetricsRenderFrameObserver::OnFrameDetached() {
WillDetach(blink::DetachReason::kNavigation); WillDetach(blink::DetachReason::kNavigation);
} }
bool MetricsRenderFrameObserver::SetUpSmoothnessReporting( bool MetricsRenderFrameObserver::SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion& shared_memory) { base::ReadOnlySharedMemoryRegion& shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion& shared_memory_dropped_frames) {
if (page_timing_metrics_sender_) { if (page_timing_metrics_sender_) {
page_timing_metrics_sender_->SetUpSmoothnessReporting( page_timing_metrics_sender_->SetUpUkmReporting(
std::move(shared_memory)); std::move(shared_memory_smoothness),
std::move(shared_memory_dropped_frames));
} else { } else {
ukm_smoothness_data_ = std::move(shared_memory); ukm_smoothness_data_ = std::move(shared_memory_smoothness);
ukm_dropped_frames_data_ = std::move(shared_memory_dropped_frames);
} }
return true; return true;
} }
@ -479,9 +484,9 @@ void MetricsRenderFrameObserver::SendMetrics() {
} }
void MetricsRenderFrameObserver::OnMetricsSenderCreated() { void MetricsRenderFrameObserver::OnMetricsSenderCreated() {
if (ukm_smoothness_data_.IsValid()) { if (ukm_smoothness_data_.IsValid() && ukm_dropped_frames_data_.IsValid()) {
page_timing_metrics_sender_->SetUpSmoothnessReporting( page_timing_metrics_sender_->SetUpUkmReporting(
std::move(ukm_smoothness_data_)); std::move(ukm_smoothness_data_), std::move(ukm_dropped_frames_data_));
} }
// Send the latest the frame intersection update, as otherwise we may miss // Send the latest the frame intersection update, as otherwise we may miss

@ -136,8 +136,9 @@ class MetricsRenderFrameObserver : public content::RenderFrameObserver,
// blink::WebLocalFrameObserver implementation // blink::WebLocalFrameObserver implementation
void OnFrameDetached() override; void OnFrameDetached() override;
bool SetUpSmoothnessReporting( bool SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion& shared_memory) override; base::ReadOnlySharedMemoryRegion& shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion& shared_memory_dropped_frames) override;
protected: protected:
// The relative and monotonic page load timings. // The relative and monotonic page load timings.
@ -182,6 +183,7 @@ class MetricsRenderFrameObserver : public content::RenderFrameObserver,
// Handle to the shared memory for transporting smoothness related ukm data. // Handle to the shared memory for transporting smoothness related ukm data.
base::ReadOnlySharedMemoryRegion ukm_smoothness_data_; base::ReadOnlySharedMemoryRegion ukm_smoothness_data_;
base::ReadOnlySharedMemoryRegion ukm_dropped_frames_data_;
// The main frame intersection rectangle signal received before // The main frame intersection rectangle signal received before
// `page_timing_metrics_sender_` is created. The signal will be send out right // `page_timing_metrics_sender_` is created. The signal will be send out right

@ -250,9 +250,11 @@ void PageTimingMetricsSender::UpdateResourceMetadata(
it->second->SetIsMainFrameResource(is_main_frame_resource); it->second->SetIsMainFrameResource(is_main_frame_resource);
} }
void PageTimingMetricsSender::SetUpSmoothnessReporting( void PageTimingMetricsSender::SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion shared_memory) { base::ReadOnlySharedMemoryRegion shared_memory_smoothness,
sender_->SetUpSmoothnessReporting(std::move(shared_memory)); base::ReadOnlySharedMemoryRegion shared_memory_dropped_frames) {
sender_->SetUpUkmReporting(std::move(shared_memory_smoothness),
std::move(shared_memory_dropped_frames));
} }
void PageTimingMetricsSender::Update( void PageTimingMetricsSender::Update(

@ -107,7 +107,11 @@ class PageTimingMetricsSender {
void UpdateCpuTiming(base::TimeDelta task_time); void UpdateCpuTiming(base::TimeDelta task_time);
void UpdateResourceMetadata(int resource_id, bool is_main_frame_resource); void UpdateResourceMetadata(int resource_id, bool is_main_frame_resource);
void SetUpSmoothnessReporting(base::ReadOnlySharedMemoryRegion shared_memory);
void SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion shared_memory_dropped_frames);
void InitiateUserInteractionTiming(); void InitiateUserInteractionTiming();
mojom::SoftNavigationMetricsPtr GetSoftNavigationMetrics() { mojom::SoftNavigationMetricsPtr GetSoftNavigationMetrics() {
return soft_navigation_metrics_->Clone(); return soft_navigation_metrics_->Clone();

@ -25,8 +25,9 @@ class PageTimingSender {
const std::optional<blink::SubresourceLoadMetrics>& const std::optional<blink::SubresourceLoadMetrics>&
subresource_load_metrics, subresource_load_metrics,
const mojom::SoftNavigationMetricsPtr& soft_navigation_metrics) = 0; const mojom::SoftNavigationMetricsPtr& soft_navigation_metrics) = 0;
virtual void SetUpSmoothnessReporting( virtual void SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion shared_memory) = 0; base::ReadOnlySharedMemoryRegion shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion shared_memory_dropped_frames) = 0;
virtual void SendCustomUserTiming(mojom::CustomUserTimingMarkPtr timing) = 0; virtual void SendCustomUserTiming(mojom::CustomUserTimingMarkPtr timing) = 0;
}; };

@ -58,8 +58,9 @@ void RenderFrameObserver::RenderFrameGone() {
render_frame_ = nullptr; render_frame_ = nullptr;
} }
bool RenderFrameObserver::SetUpSmoothnessReporting( bool RenderFrameObserver::SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion& shared_memory) { base::ReadOnlySharedMemoryRegion& shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion& shared_memory_dropped_frames) {
return false; return false;
} }

@ -370,11 +370,12 @@ class CONTENT_EXPORT RenderFrameObserver
const std::string& interface_name, const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle* handle); mojo::ScopedInterfaceEndpointHandle* handle);
// The smoothness metrics is shared over shared-memory. The interested // The smoothness and dropped frames metrics is shared over shared-memory. The
// observer should invalidate |shared_memory| (by std::move()'ing it), and // interested observer should invalidate |shared_memory| (by std::move()'ing
// return true. All other observers should return false (default). // it), and return true. All other observers should return false (default).
virtual bool SetUpSmoothnessReporting( virtual bool SetUpUkmReporting(
base::ReadOnlySharedMemoryRegion& shared_memory); base::ReadOnlySharedMemoryRegion& shared_memory_smoothness,
base::ReadOnlySharedMemoryRegion& shared_memory_dropped_frames);
#if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC) #if BUILDFLAG(CONTENT_ENABLE_LEGACY_IPC)
// IPC::Listener implementation. // IPC::Listener implementation.

@ -2142,17 +2142,19 @@ void RenderFrameImpl::OnAssociatedInterfaceRequest(
} }
} }
void RenderFrameImpl::SetUpSharedMemoryForSmoothness( void RenderFrameImpl::SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) { base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) {
TRACE_EVENT_WITH_FLOW0("navigation", TRACE_EVENT_WITH_FLOW0("navigation",
"RenderFrameImpl::SetUpSharedMemoryForSmoothness", "RenderFrameImpl::SetUpSharedMemoryForUkms",
TRACE_ID_LOCAL(this), TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(shared_memory.IsValid()); DCHECK(smoothness_memory.IsValid() && dropped_frames_memory.IsValid());
for (auto& observer : observers_) { for (auto& observer : observers_) {
DCHECK(shared_memory.IsValid()); DCHECK(smoothness_memory.IsValid() && dropped_frames_memory.IsValid());
if (observer.SetUpSmoothnessReporting(shared_memory)) if (observer.SetUpUkmReporting(smoothness_memory, dropped_frames_memory)) {
break; break;
}
} }
} }

@ -716,8 +716,10 @@ class CONTENT_EXPORT RenderFrameImpl
void OnFrameVisibilityChanged( void OnFrameVisibilityChanged(
blink::mojom::FrameVisibility render_status) override; blink::mojom::FrameVisibility render_status) override;
void SetUpSharedMemoryForSmoothness( void SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) override; base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) override;
blink::WebURL LastCommittedUrlForUKM() override; blink::WebURL LastCommittedUrlForUKM() override;
void ScriptedPrint() override; void ScriptedPrint() override;

@ -834,9 +834,10 @@ class BLINK_EXPORT WebLocalFrameClient {
virtual void OnFrameVisibilityChanged(mojom::FrameVisibility render_status) {} virtual void OnFrameVisibilityChanged(mojom::FrameVisibility render_status) {}
// Called after a navigation which set the shared memory region for // Called after a navigation which set the shared memory region for
// tracking smoothness via UKM. // tracking smoothness and dropped frames UKMs.
virtual void SetUpSharedMemoryForSmoothness( virtual void SetUpSharedMemoryForUkms(
base::ReadOnlySharedMemoryRegion shared_memory) {} base::ReadOnlySharedMemoryRegion smoothness_memory,
base::ReadOnlySharedMemoryRegion dropped_frames_memory) {}
// Returns the last commited URL used for UKM. This is slightly different // Returns the last commited URL used for UKM. This is slightly different
// than the document's URL because it will contain a data URL if a base URL // than the document's URL because it will contain a data URL if a base URL

@ -563,10 +563,13 @@ void LocalFrameClientImpl::DispatchDidCommitLoad(
web_frame_->GetDocument().GetUkmSourceId(), web_frame_->GetDocument().GetUkmSourceId(),
KURL(web_frame_->Client()->LastCommittedUrlForUKM())); KURL(web_frame_->Client()->LastCommittedUrlForUKM()));
auto shmem = frame_widget->CreateSharedMemoryForSmoothnessUkm(); auto smoothness_shmem =
if (shmem.IsValid()) { frame_widget->CreateSharedMemoryForSmoothnessUkm();
web_frame_->Client()->SetUpSharedMemoryForSmoothness( auto dropped_frames_shmem =
std::move(shmem)); frame_widget->CreateSharedMemoryForDroppedFramesUkm();
if (smoothness_shmem.IsValid() && dropped_frames_shmem.IsValid()) {
web_frame_->Client()->SetUpSharedMemoryForUkms(
std::move(smoothness_shmem), std::move(dropped_frames_shmem));
} }
} }
} }

@ -5227,6 +5227,11 @@ WebFrameWidgetImpl::CreateSharedMemoryForSmoothnessUkm() {
return LayerTreeHost()->CreateSharedMemoryForSmoothnessUkm(); return LayerTreeHost()->CreateSharedMemoryForSmoothnessUkm();
} }
base::ReadOnlySharedMemoryRegion
WebFrameWidgetImpl::CreateSharedMemoryForDroppedFramesUkm() {
return LayerTreeHost()->CreateSharedMemoryForDroppedFramesUkm();
}
bool WebFrameWidgetImpl::CanComposeInline() { bool WebFrameWidgetImpl::CanComposeInline() {
if (auto* plugin = GetFocusedPluginContainer()) if (auto* plugin = GetFocusedPluginContainer())
return plugin->CanComposeInline(); return plugin->CanComposeInline();

@ -718,6 +718,8 @@ class CORE_EXPORT WebFrameWidgetImpl
// Ask compositor to create the shared memory for smoothness ukm region. // Ask compositor to create the shared memory for smoothness ukm region.
base::ReadOnlySharedMemoryRegion CreateSharedMemoryForSmoothnessUkm(); base::ReadOnlySharedMemoryRegion CreateSharedMemoryForSmoothnessUkm();
// Ask compositor to create the shared memory for dropped frames ukm region.
base::ReadOnlySharedMemoryRegion CreateSharedMemoryForDroppedFramesUkm();
#if BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID)
// Calculate and cache the most up to date line bounding boxes in the document // Calculate and cache the most up to date line bounding boxes in the document
// coordinate space. // coordinate space.