Commit 941ebc91 authored by Sadrul Habib Chowdhury's avatar Sadrul Habib Chowdhury Committed by Commit Bot

[cc/metrics] Introduce TotalFrameCounter.

TotalFrameCounter counts the number of vsyncs the compositor was visible
for. This, in combination with DroppedFrameCounter::total_dropped() can
be used to measure the overall dropped-frame metric for the page.

BUG=1115376

Change-Id: I73959aa8ade0ebd56df6a2f31f7f1e171c3f7727
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2233302Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Commit-Queue: Sadrul Chowdhury <sadrul@chromium.org>
Cr-Commit-Position: refs/heads/master@{#799991}
parent e45f0c4d
......@@ -184,6 +184,8 @@ cc_component("cc") {
"metrics/lcd_text_metrics_reporter.h",
"metrics/throughput_ukm_reporter.cc",
"metrics/throughput_ukm_reporter.h",
"metrics/total_frame_counter.cc",
"metrics/total_frame_counter.h",
"metrics/video_playback_roughness_reporter.cc",
"metrics/video_playback_roughness_reporter.h",
"raster/bitmap_raster_buffer_provider.cc",
......@@ -679,6 +681,7 @@ cc_test("cc_unittests") {
"metrics/frame_sequence_metrics_unittest.cc",
"metrics/frame_sequence_tracker_unittest.cc",
"metrics/jank_metrics_unittest.cc",
"metrics/total_frame_counter_unittest.cc",
"metrics/video_playback_roughness_reporter_unittest.cc",
"mojo_embedder/async_layer_tree_frame_sink_unittest.cc",
"paint/clear_for_opaque_raster_unittest.cc",
......
......@@ -9,7 +9,6 @@
#include <limits>
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
namespace cc {
......
......@@ -10,7 +10,6 @@
#include <memory>
#include "base/containers/ring_buffer.h"
#include "base/time/time.h"
namespace cc {
......@@ -23,6 +22,7 @@ class DroppedFrameCounter {
kFrameStatePartial,
kFrameStateComplete
};
DroppedFrameCounter();
DroppedFrameCounter(const DroppedFrameCounter&) = delete;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/metrics/total_frame_counter.h"
#include "base/logging.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
namespace cc {
TotalFrameCounter::TotalFrameCounter() = default;
void TotalFrameCounter::OnShow(base::TimeTicks timestamp) {
DCHECK(last_shown_timestamp_.is_null());
DCHECK(latest_interval_.is_zero());
last_shown_timestamp_ = timestamp;
}
void TotalFrameCounter::OnHide(base::TimeTicks timestamp) {
// It is possible to hide right after being shown before receiving any
// BeginFrameArgs.
if (!latest_interval_.is_zero())
UpdateTotalFramesSinceLastVisible(timestamp);
last_shown_timestamp_ = base::TimeTicks();
latest_interval_ = base::TimeDelta();
}
void TotalFrameCounter::OnBeginFrame(const viz::BeginFrameArgs& args) {
// In tests, it is possible to receive begin-frames when invisible. Ignore
// these.
if (last_shown_timestamp_.is_null())
return;
if (!latest_interval_.is_zero() && latest_interval_ != args.interval) {
UpdateTotalFramesSinceLastVisible(args.frame_time);
last_shown_timestamp_ = args.frame_time;
}
latest_interval_ = args.interval;
}
void TotalFrameCounter::Reset() {
total_frames_ = 0;
latest_interval_ = {};
// If the compositor is visible, then update the visible timestamp to current
// time.
if (!last_shown_timestamp_.is_null())
last_shown_timestamp_ = base::TimeTicks::Now();
}
void TotalFrameCounter::UpdateTotalFramesSinceLastVisible(
base::TimeTicks until) {
DCHECK(!until.is_null());
DCHECK(!last_shown_timestamp_.is_null());
DCHECK_GE(until, last_shown_timestamp_);
DCHECK(!latest_interval_.is_zero());
auto frames_since =
std::round((until - last_shown_timestamp_) / latest_interval_);
total_frames_ += frames_since;
}
} // namespace cc
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CC_METRICS_TOTAL_FRAME_COUNTER_H_
#define CC_METRICS_TOTAL_FRAME_COUNTER_H_
#include "base/time/time.h"
#include "cc/cc_export.h"
namespace viz {
struct BeginFrameArgs;
}
namespace cc {
// This class keeps track of how many vsyncs (frames) the compositor was visible
// for.
class CC_EXPORT TotalFrameCounter {
public:
TotalFrameCounter();
TotalFrameCounter(const TotalFrameCounter&) = delete;
TotalFrameCounter& operator=(const TotalFrameCounter&) = delete;
void Reset();
void OnShow(base::TimeTicks timestamp);
void OnHide(base::TimeTicks timestamp);
void OnBeginFrame(const viz::BeginFrameArgs& args);
size_t total_frames() const { return total_frames_; }
private:
void UpdateTotalFramesSinceLastVisible(base::TimeTicks until);
size_t total_frames_ = 0;
// The most recent vsync-interval set by the display compositor.
// Set only if the compositor is currently visible, otherwise not set.
base::TimeDelta latest_interval_;
// The time the compositor was made visible.
// Set only if the compositor is currently visible, otherwise not set.
base::TimeTicks last_shown_timestamp_;
};
} // namespace cc
#endif // CC_METRICS_TOTAL_FRAME_COUNTER_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cc/metrics/total_frame_counter.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
const uint64_t kSourceId = 1;
TEST(TotalFrameCounterTest, Basic) {
TotalFrameCounter counter;
uint64_t sequence_number = 1;
auto frame_time = base::TimeTicks::Now();
const auto interval = base::TimeDelta::FromMillisecondsD(16.67);
auto args = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
frame_time + interval, interval, viz::BeginFrameArgs::NORMAL);
counter.OnShow(frame_time);
counter.OnBeginFrame(args);
auto advance = base::TimeDelta::FromSeconds(1);
frame_time += advance;
counter.OnHide(frame_time);
EXPECT_EQ(counter.total_frames(), 60u);
}
TEST(TotalFrameCounterTest, BeginFrameIntervalChange) {
TotalFrameCounter counter;
uint64_t sequence_number = 1;
auto frame_time = base::TimeTicks::Now();
auto interval = base::TimeDelta::FromMillisecondsD(16.67);
// Make the page visible at the default frame rate.
auto args = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
frame_time + interval, interval, viz::BeginFrameArgs::NORMAL);
counter.OnShow(frame_time);
counter.OnBeginFrame(args);
// After 10 seconds, change the frame rate to be 120fps.
interval = base::TimeDelta::FromMillisecondsD(8.33);
frame_time += base::TimeDelta::FromSeconds(10);
args = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
frame_time + interval, interval, viz::BeginFrameArgs::NORMAL);
counter.OnBeginFrame(args);
// Hide the page after 10 more seconds.
auto advance = base::TimeDelta::FromSeconds(10);
frame_time += advance;
counter.OnHide(frame_time);
EXPECT_EQ(counter.total_frames(), 1800u);
}
TEST(TotalFrameCounterTest, VisibilityChange) {
TotalFrameCounter counter;
uint64_t sequence_number = 1;
auto frame_time = base::TimeTicks::Now();
auto interval = base::TimeDelta::FromMillisecondsD(16.67);
// Make the page visible at the default frame rate.
auto args = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
frame_time + interval, interval, viz::BeginFrameArgs::NORMAL);
counter.OnShow(frame_time);
counter.OnBeginFrame(args);
// Hide the page after 10 seconds.
frame_time += base::TimeDelta::FromSeconds(10);
counter.OnHide(frame_time);
EXPECT_EQ(counter.total_frames(), 600u);
// After 20 more seconds, make the page visible again and keep it visible for
// 5 more seconds.
frame_time += base::TimeDelta::FromSeconds(20);
counter.OnShow(frame_time);
args = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, kSourceId, sequence_number++, frame_time,
frame_time + interval, interval, viz::BeginFrameArgs::NORMAL);
counter.OnBeginFrame(args);
frame_time += base::TimeDelta::FromSeconds(5);
counter.OnHide(frame_time);
EXPECT_EQ(counter.total_frames(), 900u);
}
} // namespace
} // namespace cc
......@@ -2722,6 +2722,7 @@ bool LayerTreeHostImpl::WillBeginImplFrame(const viz::BeginFrameArgs& args) {
impl_thread_phase_ = ImplThreadPhase::INSIDE_IMPL_FRAME;
current_begin_frame_tracker_.Start(args);
frame_trackers_.NotifyBeginImplFrame(args);
total_frame_counter_.OnBeginFrame(args);
if (is_likely_to_require_a_draw_) {
// Optimistically schedule a draw. This will let us expect the tile manager
......@@ -3201,6 +3202,10 @@ void LayerTreeHostImpl::SetVisible(bool visible) {
if (visible_ == visible)
return;
visible_ = visible;
if (visible_)
total_frame_counter_.OnShow(base::TimeTicks::Now());
else
total_frame_counter_.OnHide(base::TimeTicks::Now());
DidVisibilityChange(this, visible_);
UpdateTileManagerMemoryPolicy(ActualManagedMemoryPolicy());
......@@ -4816,6 +4821,7 @@ void LayerTreeHostImpl::SetActiveURL(const GURL& url, ukm::SourceId source_id) {
// The source id has already been associated to the URL.
ukm_manager_->SetSourceId(source_id);
}
total_frame_counter_.Reset();
}
void LayerTreeHostImpl::AllocateLocalSurfaceId() {
......
......@@ -36,6 +36,7 @@
#include "cc/metrics/event_metrics.h"
#include "cc/metrics/events_metrics_manager.h"
#include "cc/metrics/frame_sequence_tracker_collection.h"
#include "cc/metrics/total_frame_counter.h"
#include "cc/paint/discardable_image_map.h"
#include "cc/paint/paint_worklet_job.h"
#include "cc/resources/ui_resource_client.h"
......@@ -87,6 +88,7 @@ class BrowserControlsOffsetManager;
class CompositorFrameReportingController;
class DebugRectHistory;
class EvictionTilePriorityQueue;
class DroppedFrameCounter;
class ImageAnimationController;
class LCDTextMetricsReporter;
class LayerImpl;
......@@ -1065,6 +1067,8 @@ class CC_EXPORT LayerTreeHostImpl : public InputHandler,
std::unique_ptr<PageScaleAnimation> page_scale_animation_;
DroppedFrameCounter dropped_frame_counter_;
TotalFrameCounter total_frame_counter_;
std::unique_ptr<MemoryHistory> memory_history_;
std::unique_ptr<DebugRectHistory> debug_rect_history_;
......
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