blob: d59cb6434dd67aa1604937c7284a5ea81d3c6fac [file] [log] [blame]
// Copyright 2015 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/compositor_frame_reporting_controller.h"
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "cc/input/scroll_input_type.h"
#include "cc/metrics/event_metrics.h"
#include "components/viz/common/frame_timing_details.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cc {
namespace {
MATCHER(IsWhitelisted,
base::StrCat({negation ? "isn't" : "is", " whitelisted"})) {
return arg.IsWhitelisted();
}
class TestCompositorFrameReportingController
: public CompositorFrameReportingController {
public:
TestCompositorFrameReportingController()
: CompositorFrameReportingController(/*should_report_metrics=*/true) {}
TestCompositorFrameReportingController(
const TestCompositorFrameReportingController& controller) = delete;
TestCompositorFrameReportingController& operator=(
const TestCompositorFrameReportingController& controller) = delete;
std::unique_ptr<CompositorFrameReporter>* reporters() { return reporters_; }
int ActiveReporters() {
int count = 0;
for (int i = 0; i < PipelineStage::kNumPipelineStages; ++i) {
if (reporters_[i])
++count;
}
return count;
}
};
class CompositorFrameReportingControllerTest : public testing::Test {
public:
CompositorFrameReportingControllerTest() : current_id_(1, 1) {
args_ = SimulateBeginFrameArgs(current_id_);
}
// The following functions simulate the actions that would
// occur for each phase of the reporting controller.
void SimulateBeginImplFrame() {
reporting_controller_.WillBeginImplFrame(args_);
}
void SimulateBeginMainFrame() {
if (!reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginImplFrame])
SimulateBeginImplFrame();
CHECK(
reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginImplFrame]);
reporting_controller_.WillBeginMainFrame(args_);
}
void SimulateCommit(std::unique_ptr<BeginMainFrameMetrics> blink_breakdown) {
if (!reporting_controller_
.reporters()[CompositorFrameReportingController::PipelineStage::
kBeginMainFrame]) {
begin_main_start_ = base::TimeTicks::Now();
SimulateBeginMainFrame();
}
CHECK(
reporting_controller_.reporters()[CompositorFrameReportingController::
PipelineStage::kBeginMainFrame]);
reporting_controller_.SetBlinkBreakdown(std::move(blink_breakdown),
begin_main_start_);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
}
void SimulateActivate() {
if (!reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kCommit])
SimulateCommit(nullptr);
CHECK(reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kCommit]);
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
last_activated_id_ = current_id_;
}
void SimulateSubmitCompositorFrame(uint32_t frame_token,
EventMetricsSet events_metrics) {
if (!reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kActivate])
SimulateActivate();
CHECK(reporting_controller_.reporters()
[CompositorFrameReportingController::PipelineStage::kActivate]);
reporting_controller_.DidSubmitCompositorFrame(frame_token, current_id_,
last_activated_id_,
std::move(events_metrics));
}
void SimulatePresentCompositorFrame() {
++next_token_;
SimulateSubmitCompositorFrame(*next_token_, {});
viz::FrameTimingDetails details = {};
details.presentation_feedback.timestamp = base::TimeTicks::Now();
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
}
viz::BeginFrameArgs SimulateBeginFrameArgs(
viz::BeginFrameId frame_id,
base::TimeTicks frame_time = base::TimeTicks::Now(),
base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16)) {
args_ = viz::BeginFrameArgs();
args_.frame_id = frame_id;
args_.frame_time = frame_time;
args_.interval = interval;
return args_;
}
void IncrementCurrentId() {
current_id_.sequence_number++;
args_.frame_id = current_id_;
}
protected:
TestCompositorFrameReportingController reporting_controller_;
viz::BeginFrameArgs args_;
viz::BeginFrameId current_id_;
viz::BeginFrameId last_activated_id_;
base::TimeTicks begin_main_start_;
viz::FrameTokenGenerator next_token_;
};
TEST_F(CompositorFrameReportingControllerTest, ActiveReporterCounts) {
// Check that there are no leaks with the CompositorFrameReporter
// objects no matter what the sequence of scheduled actions is
// Note that due to DCHECKs in WillCommit(), WillActivate(), etc., it
// is impossible to have 2 reporters both in BMF or Commit
// Tests Cases:
// - 2 Reporters at Activate phase
// - 2 back-to-back BeginImplFrames
// - 4 Simultaneous Reporters
viz::BeginFrameId current_id_1(1, 1);
viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
viz::BeginFrameId current_id_2(1, 2);
viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
viz::BeginFrameId current_id_3(1, 3);
viz::BeginFrameArgs args_3 = SimulateBeginFrameArgs(current_id_3);
// BF
reporting_controller_.WillBeginImplFrame(args_1);
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
// BF -> BF
// Should replace previous reporter.
reporting_controller_.WillBeginImplFrame(args_2);
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
// BF -> BMF -> BF
// Should add new reporter.
reporting_controller_.WillBeginMainFrame(args_2);
reporting_controller_.WillBeginImplFrame(args_3);
EXPECT_EQ(2, reporting_controller_.ActiveReporters());
// BF -> BMF -> BF -> Commit
// Should stay same.
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
EXPECT_EQ(2, reporting_controller_.ActiveReporters());
// BF -> BMF -> BF -> Commit -> BMF -> Activate -> Commit -> Activation
// Having two reporters at Activate phase should delete the older one.
reporting_controller_.WillBeginMainFrame(args_3);
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
// There is a reporters tracking frame_3 in BeginMain state and one reporter
// for frame_2 in activate state.
EXPECT_EQ(2, reporting_controller_.ActiveReporters());
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
// Reporter in activate state for frame_2 is overwritten by the reporter for
// frame_3.
EXPECT_EQ(1, reporting_controller_.ActiveReporters());
last_activated_id_ = current_id_3;
reporting_controller_.DidSubmitCompositorFrame(0, current_id_3,
last_activated_id_, {});
EXPECT_EQ(0, reporting_controller_.ActiveReporters());
// 4 simultaneous reporters active.
SimulateActivate();
SimulateCommit(nullptr);
SimulateBeginMainFrame();
SimulateBeginImplFrame();
EXPECT_EQ(4, reporting_controller_.ActiveReporters());
// Any additional BeginImplFrame's would be ignored.
SimulateBeginImplFrame();
EXPECT_EQ(4, reporting_controller_.ActiveReporters());
}
TEST_F(CompositorFrameReportingControllerTest,
SubmittedFrameHistogramReporting) {
base::HistogramTester histogram_tester;
// 2 reporters active.
SimulateActivate();
SimulateCommit(nullptr);
// Submitting and Presenting the next reporter which will be a normal frame.
SimulatePresentCompositorFrame();
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.SendBeginMainFrameToCommit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.DroppedFrame.Commit", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.EndCommitToActivation", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.DroppedFrame.Activation",
0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.EndActivateToSubmitCompositorFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
// Submitting the next reporter will be replaced as a result of a new commit.
// And this will be reported for all stage before activate as a missed frame.
SimulateCommit(nullptr);
// Non Missed frame histogram counts should not change.
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
// Other histograms should be reported updated.
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.DroppedFrame.Commit", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.EndCommitToActivation", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.DroppedFrame.Activation",
0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.EndActivateToSubmitCompositorFrame", 0);
}
TEST_F(CompositorFrameReportingControllerTest, ImplFrameCausedNoDamage) {
base::HistogramTester histogram_tester;
SimulateBeginImplFrame();
SimulateBeginImplFrame();
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
}
TEST_F(CompositorFrameReportingControllerTest, MainFrameCausedNoDamage) {
base::HistogramTester histogram_tester;
viz::BeginFrameId current_id_1(1, 1);
viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
viz::BeginFrameId current_id_2(1, 2);
viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
viz::BeginFrameId current_id_3(1, 3);
viz::BeginFrameArgs args_3 = SimulateBeginFrameArgs(current_id_3);
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.BeginMainFrameAborted(current_id_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
reporting_controller_.DidNotProduceFrame(current_id_1);
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.WillBeginMainFrame(args_2);
reporting_controller_.OnFinishImplFrame(current_id_2);
reporting_controller_.BeginMainFrameAborted(current_id_2);
reporting_controller_.DidNotProduceFrame(current_id_2);
reporting_controller_.WillBeginImplFrame(args_3);
reporting_controller_.WillBeginMainFrame(args_3);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.SendBeginMainFrameToCommit", 0);
}
TEST_F(CompositorFrameReportingControllerTest, DidNotProduceFrame) {
base::HistogramTester histogram_tester;
viz::BeginFrameId current_id_1(1, 1);
viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
viz::BeginFrameId current_id_2(1, 2);
viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
reporting_controller_.DidNotProduceFrame(current_id_1);
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.OnFinishImplFrame(current_id_2);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.DidSubmitCompositorFrame(1, current_id_2, current_id_1,
{});
viz::FrameTimingDetails details = {};
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.SendBeginMainFrameToCommit", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
}
TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted) {
base::HistogramTester histogram_tester;
reporting_controller_.WillBeginImplFrame(args_);
reporting_controller_.WillBeginMainFrame(args_);
reporting_controller_.BeginMainFrameAborted(current_id_);
reporting_controller_.OnFinishImplFrame(current_id_);
reporting_controller_.DidSubmitCompositorFrame(1, current_id_,
last_activated_id_, {});
viz::FrameTimingDetails details = {};
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
}
TEST_F(CompositorFrameReportingControllerTest, MainFrameAborted2) {
base::HistogramTester histogram_tester;
viz::BeginFrameId current_id_1(1, 1);
viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
viz::BeginFrameId current_id_2(1, 2);
viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
viz::BeginFrameId current_id_3(1, 3);
viz::BeginFrameArgs args_3 = SimulateBeginFrameArgs(current_id_3);
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.WillBeginMainFrame(args_2);
reporting_controller_.OnFinishImplFrame(current_id_2);
reporting_controller_.BeginMainFrameAborted(current_id_2);
reporting_controller_.DidSubmitCompositorFrame(1, current_id_2, current_id_1,
{});
viz::FrameTimingDetails details = {};
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
reporting_controller_.DidSubmitCompositorFrame(2, current_id_2, current_id_1,
{});
reporting_controller_.DidPresentCompositorFrame(2, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 2);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 2);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 2);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
2);
reporting_controller_.WillBeginImplFrame(args_3);
reporting_controller_.OnFinishImplFrame(current_id_3);
reporting_controller_.DidSubmitCompositorFrame(3, current_id_3, current_id_1,
{});
reporting_controller_.DidPresentCompositorFrame(3, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.BeginImplFrameToSendBeginMainFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 3);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 2);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 3);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
3);
}
TEST_F(CompositorFrameReportingControllerTest, LongMainFrame) {
base::HistogramTester histogram_tester;
viz::BeginFrameId current_id_1(1, 1);
viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
viz::BeginFrameId current_id_2(1, 2);
viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
viz::FrameTimingDetails details = {};
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.DidSubmitCompositorFrame(1, current_id_1, current_id_1,
{});
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
// Second frame will not have the main frame update ready and will only submit
// the Impl update
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.WillBeginMainFrame(args_2);
reporting_controller_.OnFinishImplFrame(current_id_2);
reporting_controller_.DidSubmitCompositorFrame(2, current_id_2, current_id_1,
{});
reporting_controller_.DidPresentCompositorFrame(2, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 2);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 2);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
2);
}
TEST_F(CompositorFrameReportingControllerTest, LongMainFrame2) {
base::HistogramTester histogram_tester;
viz::BeginFrameId current_id_1(1, 1);
viz::BeginFrameArgs args_1 = SimulateBeginFrameArgs(current_id_1);
viz::BeginFrameId current_id_2(1, 2);
viz::BeginFrameArgs args_2 = SimulateBeginFrameArgs(current_id_2);
viz::FrameTimingDetails details = {};
reporting_controller_.WillBeginImplFrame(args_1);
reporting_controller_.OnFinishImplFrame(current_id_1);
reporting_controller_.WillBeginMainFrame(args_1);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.DidSubmitCompositorFrame(1, current_id_1, current_id_1,
{});
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
// Second frame will not have the main frame update ready and will only submit
// the Impl update
reporting_controller_.WillBeginImplFrame(args_2);
reporting_controller_.WillBeginMainFrame(args_2);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.OnFinishImplFrame(current_id_2);
reporting_controller_.DidSubmitCompositorFrame(2, current_id_2, current_id_1,
{});
reporting_controller_.DidPresentCompositorFrame(2, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 2);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
1);
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 2);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
2);
}
TEST_F(CompositorFrameReportingControllerTest, BlinkBreakdown) {
base::HistogramTester histogram_tester;
std::unique_ptr<BeginMainFrameMetrics> blink_breakdown =
std::make_unique<BeginMainFrameMetrics>();
blink_breakdown->handle_input_events = base::TimeDelta::FromMicroseconds(10);
blink_breakdown->animate = base::TimeDelta::FromMicroseconds(9);
blink_breakdown->style_update = base::TimeDelta::FromMicroseconds(8);
blink_breakdown->layout_update = base::TimeDelta::FromMicroseconds(7);
blink_breakdown->prepaint = base::TimeDelta::FromMicroseconds(6);
blink_breakdown->composite = base::TimeDelta::FromMicroseconds(5);
blink_breakdown->paint = base::TimeDelta::FromMicroseconds(4);
blink_breakdown->scrolling_coordinator = base::TimeDelta::FromMicroseconds(3);
blink_breakdown->composite_commit = base::TimeDelta::FromMicroseconds(2);
blink_breakdown->update_layers = base::TimeDelta::FromMicroseconds(1);
SimulateActivate();
SimulateCommit(std::move(blink_breakdown));
SimulatePresentCompositorFrame();
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.HandleInputEvents",
base::TimeDelta::FromMicroseconds(10).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.Animate",
base::TimeDelta::FromMicroseconds(9).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.StyleUpdate",
base::TimeDelta::FromMicroseconds(8).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.LayoutUpdate",
base::TimeDelta::FromMicroseconds(7).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.Prepaint",
base::TimeDelta::FromMicroseconds(6).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.Composite",
base::TimeDelta::FromMicroseconds(5).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.Paint",
base::TimeDelta::FromMicroseconds(4).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.ScrollingCoordinator",
base::TimeDelta::FromMicroseconds(3).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.CompositeCommit",
base::TimeDelta::FromMicroseconds(2).InMilliseconds(), 1);
histogram_tester.ExpectUniqueSample(
"CompositorLatency.SendBeginMainFrameToCommit.UpdateLayers",
base::TimeDelta::FromMicroseconds(1).InMilliseconds(), 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit.BeginMainSentToStarted", 1);
}
// If the presentation of the frame happens before deadline.
TEST_F(CompositorFrameReportingControllerTest, ReportingMissedDeadlineFrame1) {
base::HistogramTester histogram_tester;
reporting_controller_.WillBeginImplFrame(args_);
reporting_controller_.OnFinishImplFrame(current_id_);
reporting_controller_.WillBeginMainFrame(args_);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.DidSubmitCompositorFrame(1, current_id_, current_id_,
{});
viz::FrameTimingDetails details = {};
details.presentation_feedback.timestamp =
args_.frame_time + args_.interval * 1.5 -
base::TimeDelta::FromMicroseconds(100);
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.TotalLatency", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedDeadlineFrame."
"BeginImplFrameToSendBeginMainFrame",
0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedDeadlineFrame.TotalLatency", 0);
// Non-dropped cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 0, 1);
// Missed-deadline cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 1, 0);
// Dropped cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 2, 0);
}
// If the presentation of the frame happens after deadline.
TEST_F(CompositorFrameReportingControllerTest, ReportingMissedDeadlineFrame2) {
base::HistogramTester histogram_tester;
reporting_controller_.WillBeginImplFrame(args_);
reporting_controller_.OnFinishImplFrame(current_id_);
reporting_controller_.WillBeginMainFrame(args_);
reporting_controller_.WillCommit();
reporting_controller_.DidCommit();
reporting_controller_.WillActivate();
reporting_controller_.DidActivate();
reporting_controller_.DidSubmitCompositorFrame(1, current_id_, current_id_,
{});
viz::FrameTimingDetails details = {};
details.presentation_feedback.timestamp =
args_.frame_time + args_.interval * 1.5 +
base::TimeDelta::FromMicroseconds(100);
reporting_controller_.DidPresentCompositorFrame(1, details);
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.TotalLatency", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedDeadlineFrame."
"BeginImplFrameToSendBeginMainFrame",
1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.MissedDeadlineFrame.TotalLatency", 1);
// Non-dropped cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 0, 1);
// Missed-deadline cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 1, 1);
// Dropped cases.
histogram_tester.ExpectBucketCount("CompositorLatency.Type", 2, 0);
}
// Tests that EventLatency histograms are reported properly when a frame is
// presented to the user.
TEST_F(CompositorFrameReportingControllerTest,
EventLatencyForPresentedFrameReported) {
base::HistogramTester histogram_tester;
const base::TimeTicks event_time = base::TimeTicks::Now();
std::vector<EventMetrics> events_metrics = {
{ui::ET_TOUCH_PRESSED, event_time, base::nullopt},
{ui::ET_TOUCH_MOVED, event_time, base::nullopt},
{ui::ET_TOUCH_MOVED, event_time, base::nullopt},
};
EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
// Submit a compositor frame and notify CompositorFrameReporter of the events
// affecting the frame.
++next_token_;
SimulateSubmitCompositorFrame(*next_token_, {std::move(events_metrics), {}});
// Present the submitted compositor frame to the user.
const base::TimeTicks presentation_time = base::TimeTicks::Now();
viz::FrameTimingDetails details;
details.presentation_feedback.timestamp = presentation_time;
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
// Verify that EventLatency histograms are recorded.
const int latency_ms = (presentation_time - event_time).InMicroseconds();
histogram_tester.ExpectTotalCount("EventLatency.TouchPressed.TotalLatency",
1);
histogram_tester.ExpectTotalCount("EventLatency.TouchMoved.TotalLatency", 2);
histogram_tester.ExpectBucketCount("EventLatency.TouchPressed.TotalLatency",
latency_ms, 1);
histogram_tester.ExpectBucketCount("EventLatency.TouchMoved.TotalLatency",
latency_ms, 2);
}
// Tests that EventLatency histograms are reported properly for scroll events
// when a frame is presented to the user.
TEST_F(CompositorFrameReportingControllerTest,
EventLatencyScrollForPresentedFrameReported) {
base::HistogramTester histogram_tester;
const base::TimeTicks event_time = base::TimeTicks::Now();
std::vector<EventMetrics> events_metrics = {
{ui::ET_GESTURE_SCROLL_BEGIN, event_time, ScrollInputType::kWheel},
{ui::ET_GESTURE_SCROLL_UPDATE, event_time, ScrollInputType::kWheel},
{ui::ET_GESTURE_SCROLL_UPDATE, event_time, ScrollInputType::kWheel},
};
EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
// Submit a compositor frame and notify CompositorFrameReporter of the events
// affecting the frame.
++next_token_;
SimulateSubmitCompositorFrame(*next_token_, {std::move(events_metrics), {}});
// Present the submitted compositor frame to the user.
const base::TimeTicks presentation_time = base::TimeTicks::Now();
viz::FrameTimingDetails details;
details.presentation_feedback.timestamp = presentation_time;
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
// Verify that EventLatency histograms are recorded.
const int latency_ms = (presentation_time - event_time).InMicroseconds();
histogram_tester.ExpectTotalCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatency", 1);
histogram_tester.ExpectTotalCount(
"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 2);
histogram_tester.ExpectBucketCount(
"EventLatency.GestureScrollBegin.Wheel.TotalLatency", latency_ms, 1);
histogram_tester.ExpectBucketCount(
"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", latency_ms, 2);
}
// Tests that EventLatency histograms are not reported when the frame is dropped
// and not presented to the user.
TEST_F(CompositorFrameReportingControllerTest,
EventLatencyForDidNotPresentFrameNotReported) {
base::HistogramTester histogram_tester;
const base::TimeTicks event_time = base::TimeTicks::Now();
std::vector<EventMetrics> events_metrics = {
{ui::ET_TOUCH_PRESSED, event_time, base::nullopt},
{ui::ET_TOUCH_MOVED, event_time, base::nullopt},
{ui::ET_TOUCH_MOVED, event_time, base::nullopt},
};
EXPECT_THAT(events_metrics, ::testing::Each(IsWhitelisted()));
// Submit a compositor frame and notify CompositorFrameReporter of the events
// affecting the frame.
++next_token_;
SimulateSubmitCompositorFrame(*next_token_, {std::move(events_metrics), {}});
// Submit another compositor frame.
++next_token_;
IncrementCurrentId();
SimulateSubmitCompositorFrame(*next_token_, {});
// Present the second compositor frame to the uesr, dropping the first one.
viz::FrameTimingDetails details;
details.presentation_feedback.timestamp = base::TimeTicks::Now();
reporting_controller_.DidPresentCompositorFrame(*next_token_, details);
// Verify that no EventLatency histogram is recorded.
histogram_tester.ExpectTotalCount("EventLatency.TouchPressed.TotalLatency",
0);
histogram_tester.ExpectTotalCount("EventLatency.TouchMoved.TotalLatency", 0);
}
} // namespace
} // namespace cc