blob: d7defb4d11d49019a522436a3f417f48d911f263 [file] [log] [blame]
// Copyright 2019 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_reporter.h"
#include <algorithm>
#include <memory>
#include <utility>
#include <vector>
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/simple_test_tick_clock.h"
#include "cc/metrics/compositor_frame_reporting_controller.h"
#include "cc/metrics/dropped_frame_counter.h"
#include "cc/metrics/event_metrics.h"
#include "cc/metrics/total_frame_counter.h"
#include "components/viz/common/frame_timing_details.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/types/scroll_input_type.h"
namespace cc {
namespace {
using ::testing::Each;
using ::testing::IsEmpty;
using ::testing::NotNull;
class CompositorFrameReporterTest : public testing::Test {
public:
CompositorFrameReporterTest() : pipeline_reporter_(CreatePipelineReporter()) {
AdvanceNowByMs(1);
dropped_frame_counter_.set_total_counter(&total_frame_counter_);
}
protected:
base::TimeTicks AdvanceNowByMs(int advance_ms) {
test_tick_clock_.Advance(base::TimeDelta::FromMicroseconds(advance_ms));
return test_tick_clock_.NowTicks();
}
base::TimeTicks Now() { return test_tick_clock_.NowTicks(); }
std::unique_ptr<BeginMainFrameMetrics> BuildBlinkBreakdown() {
auto breakdown = std::make_unique<BeginMainFrameMetrics>();
breakdown->handle_input_events = base::TimeDelta::FromMicroseconds(10);
breakdown->animate = base::TimeDelta::FromMicroseconds(9);
breakdown->style_update = base::TimeDelta::FromMicroseconds(8);
breakdown->layout_update = base::TimeDelta::FromMicroseconds(7);
breakdown->compositing_inputs = base::TimeDelta::FromMicroseconds(6);
breakdown->prepaint = base::TimeDelta::FromMicroseconds(5);
breakdown->compositing_assignments = base::TimeDelta::FromMicroseconds(4);
breakdown->paint = base::TimeDelta::FromMicroseconds(3);
breakdown->composite_commit = base::TimeDelta::FromMicroseconds(2);
breakdown->update_layers = base::TimeDelta::FromMicroseconds(1);
// Advance now by the sum of the breakdowns.
AdvanceNowByMs(10 + 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1);
return breakdown;
}
viz::FrameTimingDetails BuildVizBreakdown() {
viz::FrameTimingDetails viz_breakdown;
viz_breakdown.received_compositor_frame_timestamp = AdvanceNowByMs(1);
viz_breakdown.draw_start_timestamp = AdvanceNowByMs(2);
viz_breakdown.swap_timings.swap_start = AdvanceNowByMs(3);
viz_breakdown.swap_timings.swap_end = AdvanceNowByMs(4);
viz_breakdown.presentation_feedback.timestamp = AdvanceNowByMs(5);
return viz_breakdown;
}
std::unique_ptr<EventMetrics> CreateEventMetrics(
ui::EventType type,
base::Optional<EventMetrics::ScrollUpdateType> scroll_update_type,
base::Optional<ui::ScrollInputType> scroll_input_type) {
const base::TimeTicks event_time = AdvanceNowByMs(3);
AdvanceNowByMs(3);
std::unique_ptr<EventMetrics> metrics = EventMetrics::CreateForTesting(
type, scroll_update_type, scroll_input_type, event_time,
&test_tick_clock_);
if (metrics) {
AdvanceNowByMs(3);
metrics->SetDispatchStageTimestamp(
EventMetrics::DispatchStage::kRendererCompositorStarted);
AdvanceNowByMs(3);
metrics->SetDispatchStageTimestamp(
EventMetrics::DispatchStage::kRendererCompositorFinished);
}
return metrics;
}
std::vector<base::TimeTicks> GetEventTimestamps(
const EventMetrics::List& events_metrics) {
std::vector<base::TimeTicks> event_times;
event_times.reserve(events_metrics.size());
std::transform(events_metrics.cbegin(), events_metrics.cend(),
std::back_inserter(event_times),
[](const auto& event_metrics) {
return event_metrics->GetDispatchStageTimestamp(
EventMetrics::DispatchStage::kGenerated);
});
return event_times;
}
std::unique_ptr<CompositorFrameReporter> CreatePipelineReporter() {
auto reporter = std::make_unique<CompositorFrameReporter>(
ActiveTrackers(), viz::BeginFrameArgs(),
/*latency_ukm_reporter=*/nullptr,
/*should_report_metrics=*/true,
CompositorFrameReporter::SmoothThread::kSmoothBoth,
FrameSequenceMetrics::ThreadType::kUnknown,
/*layer_tree_host_id=*/1, &dropped_frame_counter_);
reporter->set_tick_clock(&test_tick_clock_);
return reporter;
}
// This should be defined before |pipeline_reporter_| so it is created before
// and destroyed after that.
base::SimpleTestTickClock test_tick_clock_;
DroppedFrameCounter dropped_frame_counter_;
TotalFrameCounter total_frame_counter_;
std::unique_ptr<CompositorFrameReporter> pipeline_reporter_;
};
TEST_F(CompositorFrameReporterTest, MainFrameAbortedReportingTest) {
base::HistogramTester histogram_tester;
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
Now());
EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now());
EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::
kSubmitCompositorFrameToPresentationCompositorFrame,
Now());
EXPECT_EQ(3, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame, Now());
EXPECT_EQ(4, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount(
"CompositorLatency.BeginImplFrameToSendBeginMainFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SubmitCompositorFrameToPresentationCompositorFrame",
1);
}
TEST_F(CompositorFrameReporterTest, ReplacedByNewReporterReportingTest) {
base::HistogramTester histogram_tester;
pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
Now());
EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndCommitToActivation, Now());
EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(2);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kReplacedByNewReporter,
Now());
EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.EndCommitToActivation",
0);
}
TEST_F(CompositorFrameReporterTest, SubmittedFrameReportingTest) {
base::HistogramTester histogram_tester;
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kActivation, Now());
EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(2);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame, Now());
EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount("CompositorLatency.Activation", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.TotalLatency", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.DroppedFrame.Activation",
0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.EndActivateToSubmitCompositorFrame", 0);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.TotalLatency", 0);
histogram_tester.ExpectBucketCount("CompositorLatency.Activation", 3, 1);
histogram_tester.ExpectBucketCount(
"CompositorLatency.EndActivateToSubmitCompositorFrame", 2, 1);
histogram_tester.ExpectBucketCount("CompositorLatency.TotalLatency", 5, 1);
}
TEST_F(CompositorFrameReporterTest, SubmittedDroppedFrameReportingTest) {
base::HistogramTester histogram_tester;
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit, Now());
EXPECT_EQ(0, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(CompositorFrameReporter::StageType::kCommit,
Now());
EXPECT_EQ(1, pipeline_reporter_->stage_history_size_for_testing());
AdvanceNowByMs(2);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kDidNotPresentFrame,
Now());
EXPECT_EQ(2, pipeline_reporter_->stage_history_size_for_testing());
pipeline_reporter_ = nullptr;
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.SendBeginMainFrameToCommit", 1);
histogram_tester.ExpectTotalCount("CompositorLatency.DroppedFrame.Commit", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.DroppedFrame.TotalLatency", 1);
histogram_tester.ExpectTotalCount(
"CompositorLatency.SendBeginMainFrameToCommit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.Commit", 0);
histogram_tester.ExpectTotalCount("CompositorLatency.TotalLatency", 0);
histogram_tester.ExpectBucketCount(
"CompositorLatency.DroppedFrame.SendBeginMainFrameToCommit", 3, 1);
histogram_tester.ExpectBucketCount("CompositorLatency.DroppedFrame.Commit", 2,
1);
histogram_tester.ExpectBucketCount(
"CompositorLatency.DroppedFrame.TotalLatency", 5, 1);
}
// Tests that when a frame is presented to the user, total event latency metrics
// are reported properly.
TEST_F(CompositorFrameReporterTest,
EventLatencyTotalForPresentedFrameReported) {
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
CreateEventMetrics(ui::ET_TOUCH_PRESSED, base::nullopt, base::nullopt),
CreateEventMetrics(ui::ET_TOUCH_MOVED, base::nullopt, base::nullopt),
CreateEventMetrics(ui::ET_TOUCH_MOVED, base::nullopt, base::nullopt),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
std::make_move_iterator(std::begin(event_metrics_ptrs)),
std::make_move_iterator(std::end(event_metrics_ptrs)));
std::vector<base::TimeTicks> event_times = GetEventTimestamps(events_metrics);
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
Now());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::
kSubmitCompositorFrameToPresentationCompositorFrame,
Now());
pipeline_reporter_->AddEventsMetrics(std::move(events_metrics));
const base::TimeTicks presentation_time = AdvanceNowByMs(3);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame,
presentation_time);
pipeline_reporter_ = nullptr;
struct {
const char* name;
const base::HistogramBase::Count count;
} expected_counts[] = {
{"EventLatency.TouchPressed.TotalLatency", 1},
{"EventLatency.TouchMoved.TotalLatency", 2},
{"EventLatency.TotalLatency", 3},
};
for (const auto& expected_count : expected_counts) {
histogram_tester.ExpectTotalCount(expected_count.name,
expected_count.count);
}
struct {
const char* name;
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.TouchPressed.TotalLatency",
(presentation_time - event_times[0]).InMicroseconds()},
{"EventLatency.TouchMoved.TotalLatency",
(presentation_time - event_times[1]).InMicroseconds()},
{"EventLatency.TouchMoved.TotalLatency",
(presentation_time - event_times[2]).InMicroseconds()},
{"EventLatency.TotalLatency",
(presentation_time - event_times[0]).InMicroseconds()},
{"EventLatency.TotalLatency",
(presentation_time - event_times[1]).InMicroseconds()},
{"EventLatency.TotalLatency",
(presentation_time - event_times[2]).InMicroseconds()},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
expected_latency.latency_ms, 1);
}
}
// Tests that when a frame is presented to the user, total scroll event latency
// metrics are reported properly.
TEST_F(CompositorFrameReporterTest,
EventLatencyScrollTotalForPresentedFrameReported) {
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
CreateEventMetrics(ui::ET_GESTURE_SCROLL_BEGIN, base::nullopt,
ui::ScrollInputType::kWheel),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
EventMetrics::ScrollUpdateType::kStarted,
ui::ScrollInputType::kWheel),
CreateEventMetrics(ui::ET_GESTURE_SCROLL_UPDATE,
EventMetrics::ScrollUpdateType::kContinued,
ui::ScrollInputType::kWheel),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
std::make_move_iterator(std::begin(event_metrics_ptrs)),
std::make_move_iterator(std::end(event_metrics_ptrs)));
std::vector<base::TimeTicks> event_times = GetEventTimestamps(events_metrics);
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
Now());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::
kSubmitCompositorFrameToPresentationCompositorFrame,
Now());
pipeline_reporter_->AddEventsMetrics(std::move(events_metrics));
AdvanceNowByMs(3);
viz::FrameTimingDetails viz_breakdown = BuildVizBreakdown();
pipeline_reporter_->SetVizBreakdown(viz_breakdown);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kPresentedFrame,
viz_breakdown.presentation_feedback.timestamp);
pipeline_reporter_ = nullptr;
struct {
const char* name;
const base::HistogramBase::Count count;
} expected_counts[] = {
{"EventLatency.GestureScrollBegin.Wheel.TotalLatency", 1},
{"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapBegin", 1},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatency", 1},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
1},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatency", 1},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin", 1},
{"EventLatency.TotalLatency", 3},
};
for (const auto& expected_count : expected_counts) {
histogram_tester.ExpectTotalCount(expected_count.name,
expected_count.count);
}
const base::TimeTicks presentation_time =
viz_breakdown.presentation_feedback.timestamp;
const base::TimeTicks swap_begin_time = viz_breakdown.swap_timings.swap_start;
struct {
const char* name;
const base::HistogramBase::Sample latency_ms;
} expected_latencies[] = {
{"EventLatency.GestureScrollBegin.Wheel.TotalLatency",
(presentation_time - event_times[0]).InMicroseconds()},
{"EventLatency.GestureScrollBegin.Wheel.TotalLatencyToSwapBegin",
(swap_begin_time - event_times[0]).InMicroseconds()},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatency",
(presentation_time - event_times[1]).InMicroseconds()},
{"EventLatency.FirstGestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
(swap_begin_time - event_times[1]).InMicroseconds()},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatency",
(presentation_time - event_times[2]).InMicroseconds()},
{"EventLatency.GestureScrollUpdate.Wheel.TotalLatencyToSwapBegin",
(swap_begin_time - event_times[2]).InMicroseconds()},
};
for (const auto& expected_latency : expected_latencies) {
histogram_tester.ExpectBucketCount(expected_latency.name,
expected_latency.latency_ms, 1);
}
}
// Tests that when the frame is not presented to the user, event latency metrics
// are not reported.
TEST_F(CompositorFrameReporterTest,
EventLatencyForDidNotPresentFrameNotReported) {
base::HistogramTester histogram_tester;
std::unique_ptr<EventMetrics> event_metrics_ptrs[] = {
CreateEventMetrics(ui::ET_TOUCH_PRESSED, base::nullopt, base::nullopt),
CreateEventMetrics(ui::ET_TOUCH_MOVED, base::nullopt, base::nullopt),
CreateEventMetrics(ui::ET_TOUCH_MOVED, base::nullopt, base::nullopt),
};
EXPECT_THAT(event_metrics_ptrs, Each(NotNull()));
EventMetrics::List events_metrics(
std::make_move_iterator(std::begin(event_metrics_ptrs)),
std::make_move_iterator(std::end(event_metrics_ptrs)));
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kBeginImplFrameToSendBeginMainFrame,
Now());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::kEndActivateToSubmitCompositorFrame,
Now());
AdvanceNowByMs(3);
pipeline_reporter_->StartStage(
CompositorFrameReporter::StageType::
kSubmitCompositorFrameToPresentationCompositorFrame,
Now());
pipeline_reporter_->AddEventsMetrics(std::move(events_metrics));
AdvanceNowByMs(3);
pipeline_reporter_->TerminateFrame(
CompositorFrameReporter::FrameTerminationStatus::kDidNotPresentFrame,
Now());
pipeline_reporter_ = nullptr;
EXPECT_THAT(histogram_tester.GetTotalCountsForPrefix("EventLaterncy."),
IsEmpty());
}
// Verifies that partial update dependent queues are working as expected when
// they reach their maximum capacity.
TEST_F(CompositorFrameReporterTest, PartialUpdateDependentQueues) {
// This constant should match the constant with the same name in
// compositor_frame_reporter.cc.
const size_t kMaxOwnedPartialUpdateDependents = 300u;
// The first three dependent reporters for the front of the queue.
std::unique_ptr<CompositorFrameReporter> deps[] = {
CreatePipelineReporter(),
CreatePipelineReporter(),
CreatePipelineReporter(),
};
// Set `deps[0]` as a dependent of the main reporter and adopt it at the same
// time. This should enqueue it in both non-owned and owned dependents queues.
deps[0]->SetPartialUpdateDecider(pipeline_reporter_.get());
pipeline_reporter_->AdoptReporter(std::move(deps[0]));
DCHECK_EQ(1u,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
1u,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Set `deps[1]` as a dependent of the main reporter, but don't adopt it yet.
// This should enqueue it in non-owned dependents queue only.
deps[1]->SetPartialUpdateDecider(pipeline_reporter_.get());
DCHECK_EQ(2u,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
1u,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Set `deps[2]` as a dependent of the main reporter and adopt it at the same
// time. This should enqueue it in both non-owned and owned dependents queues.
deps[2]->SetPartialUpdateDecider(pipeline_reporter_.get());
pipeline_reporter_->AdoptReporter(std::move(deps[2]));
DCHECK_EQ(3u,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
2u,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Now adopt `deps[1]` to enqueue it in the owned dependents queue.
pipeline_reporter_->AdoptReporter(std::move(deps[1]));
DCHECK_EQ(3u,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
3u,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Fill the queues with more dependent reporters until the capacity is
// reached. After this, the queues should look like this (assuming n equals
// `kMaxOwnedPartialUpdateDependents`):
// Partial Update Dependents: [0, 1, 2, 3, 4, ..., n-1]
// Owned Partial Update Dependents: [0, 2, 1, 3, 4, ..., n-1]
while (
pipeline_reporter_->owned_partial_update_dependents_size_for_testing() <
kMaxOwnedPartialUpdateDependents) {
std::unique_ptr<CompositorFrameReporter> dependent =
CreatePipelineReporter();
dependent->SetPartialUpdateDecider(pipeline_reporter_.get());
pipeline_reporter_->AdoptReporter(std::move(dependent));
}
DCHECK_EQ(kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Enqueue a new dependent reporter. This should pop `deps[0]` from the front
// of the owned dependents queue and destroy it. Since the same one is in
// front of the non-owned dependents queue, it will be popped out of that
// queue, too. The queues will look like this:
// Partial Update Dependents: [1, 2, 3, 4, ..., n]
// Owned Partial Update Dependents: [2, 1, 3, 4, ..., n]
auto new_dep = CreatePipelineReporter();
new_dep->SetPartialUpdateDecider(pipeline_reporter_.get());
pipeline_reporter_->AdoptReporter(std::move(new_dep));
DCHECK_EQ(kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Enqueue another new dependent reporter. This should pop `deps[2]` from the
// front of the owned dependents queue and destroy it. Since another reporter
// is in front of the non-owned dependents queue it won't be popped out of
// that queue. The queues will look like this:
// Partial Update Dependents: [2, 3, 4, ..., n+1]
// Owned Partial Update Dependents: [2, nullptr, 3, 4, ..., n+1]
new_dep = CreatePipelineReporter();
new_dep->SetPartialUpdateDecider(pipeline_reporter_.get());
pipeline_reporter_->AdoptReporter(std::move(new_dep));
DCHECK_EQ(kMaxOwnedPartialUpdateDependents + 1,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
// Enqueue yet another new dependent reporter. This should pop `deps[1]` from
// the front of the owned dependents queue and destroy it. Since the same one
// is in front of the non-owned dependents queue followed by `deps[2]` which
// was destroyed in the previous step, they will be popped out of that queue,
// too. The queues will look like this:
// Partial Update Dependents: [3, 4, ..., n+2]
// Owned Partial Update Dependents: [3, 4, ..., n+2]
new_dep = CreatePipelineReporter();
new_dep->SetPartialUpdateDecider(pipeline_reporter_.get());
pipeline_reporter_->AdoptReporter(std::move(new_dep));
DCHECK_EQ(kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->partial_update_dependents_size_for_testing());
DCHECK_EQ(
kMaxOwnedPartialUpdateDependents,
pipeline_reporter_->owned_partial_update_dependents_size_for_testing());
}
} // namespace
} // namespace cc