1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/metrics/jank_metrics.h"
9 #include <unordered_map>
13 #include "base/strings/strcat.h"
14 #include "base/test/metrics/histogram_tester.h"
15 #include "cc/metrics/frame_sequence_tracker.h"
16 #include "cc/metrics/throughput_ukm_reporter.h"
17 #include "cc/trees/ukm_manager.h"
18 #include "components/ukm/test_ukm_recorder.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 const base::TimeDelta kDefaultFrameInterval = base::Milliseconds(16.67);
25 // All sequence numbers for simulated frame events will start at this number.
26 // This makes it easier to numerically distinguish sequence numbers versus
27 // frame tokens, which always start at 1.
28 const uint32_t kSequenceNumberStartsAt = 100u;
30 const char* kAllSequencesMetricName = "Graphics.Smoothness.Jank.AllSequences";
31 const char* kAllAnimationsMetricName = "Graphics.Smoothness.Jank.AllAnimations";
32 const char* kAllInteractionsMetricName =
33 "Graphics.Smoothness.Jank.AllInteractions";
39 class JankMetricsTest : public testing::Test {
41 JankMetricsTest() = default;
42 ~JankMetricsTest() override = default;
44 // Simulate a series of Submit, NoUpdate, and Presentation events and notify
45 // |jank_reporter|, as specified by |frame_sequences|. The exact presentation
46 // time of frames can be slightly manipulated by |presentation_time_shifts|.
47 void SimulateFrameSequence(
48 JankMetrics* jank_reporter,
49 const std::array<std::string, 3>& frame_sequences,
50 const std::unordered_map<char, double>& presentation_time_shifts = {}) {
51 // |frame_sequences| is an array of 3 strings of EQUAL LENGTH, representing
52 // the (S)UBMIT, (N)O-UPDATE, (P)RESENTATION events, respectively. In all 3
54 // any char == a vsync interval (16.67ms) with a unique sequence number.
55 // '-' == no event in this vsync interval.
57 // [a-zA-Z] == A SUBMIT occurs at this vsync interval. Each symbol in this
58 // string must be unique.
59 // In NO-UPDATE string:
60 // Any non '-' letter == A NO-UPDATE frame is reported at this vsync
62 // In PRESENTATION string:
63 // [a-zA-Z] == A PRESENTATION occurs at this vsync interval. Each
64 // symbol must be unique and MUST HAVE APPEARED in the SUBMIT string.
66 // NOTE this test file stylistically denotes the frames that should jank
67 // with uppercases (although this is not a strict).
69 // Each item in |presentation_time_shifts| maps a presentation frame letter
70 // (must have appeared in string P) to how much time (in ms) this
71 // presentation deviates from expected. For example: {'a': -3.2} means frame
72 // 'a' is presented 3.2ms before expected.
78 // presentation_time_shifts = {'c':-8.4, 'D':8.4}
80 // means submit at vsync 0, 2, 5, 8, presentation at 1, 3, 7, 9. Due to the
81 // no-update frames 3 and 4, no janks will be reported for 'c'. However, the
82 // large fluctuation of presentation time of 'c' and 'D', there is a jank
85 // Without the no-update frames and presentation_time_shifts, one jank would
86 // have been reported at 'c'.
87 auto& submits = frame_sequences[0];
88 auto& ignores = frame_sequences[1];
89 auto& presnts = frame_sequences[2];
91 // All three sequences must have the same size.
92 EXPECT_EQ(submits.size(), ignores.size());
93 EXPECT_EQ(submits.size(), presnts.size());
95 // Map submitted frame to their tokens
96 std::unordered_map<char, uint32_t> submit_to_token;
98 base::TimeTicks start_time = base::TimeTicks::Now();
100 // Scan S to collect all symbols
101 for (uint32_t frame_token = 1, i = 0; i < submits.size(); ++i) {
102 uint32_t sequence_number = kSequenceNumberStartsAt + i;
103 if (submits[i] != '-') {
104 submit_to_token[submits[i]] = frame_token;
105 jank_reporter->AddSubmitFrame(/*frame_token=*/frame_token,
106 /*sequence_number=*/sequence_number);
110 if (ignores[i] != '-') {
111 jank_reporter->AddFrameWithNoUpdate(
112 /*sequence_number=*/sequence_number,
113 /*frame_interval=*/kDefaultFrameInterval);
116 if (presnts[i] != '-') {
117 // The present frame must have been previously submitted
118 EXPECT_EQ(submit_to_token.count(presnts[i]), 1u);
120 double presentation_offset = 0.0; // ms
121 if (presentation_time_shifts.count(presnts[i]))
122 presentation_offset = presentation_time_shifts.at(presnts[i]);
124 jank_reporter->AddPresentedFrame(
125 /*presented_frame_token=*/submit_to_token[presnts[i]],
126 /*current_presentation_timestamp=*/start_time +
127 i * kDefaultFrameInterval +
128 base::Milliseconds(presentation_offset),
129 /*frame_interval=*/kDefaultFrameInterval);
130 submit_to_token.erase(presnts[i]);
136 TEST_F(JankMetricsTest, CompositorAnimationOneJankWithMildFluctuation) {
137 base::HistogramTester histogram_tester;
138 FrameSequenceTrackerType tracker_type =
139 FrameSequenceTrackerType::kCompositorAnimation;
140 FrameInfo::SmoothEffectDrivingThread thread_type =
141 FrameInfo::SmoothEffectDrivingThread::kCompositor;
142 JankMetrics jank_reporter{tracker_type, thread_type};
144 // One Jank; there are no no-update frames. The fluctuation in presentation of
145 // 'd' is not big enough to cause another jank.
146 SimulateFrameSequence(&jank_reporter,
148 /*submit */ "ab-C-d",
149 /*noupdate */ "------",
150 /*present */ "ab-C-d",
152 {{'d', +8.0 /*ms*/}});
153 jank_reporter.ReportJankMetrics(100u);
155 // One sample of 1 janks reported for "Compositor".
157 "Graphics.Smoothness.Jank.Compositor.CompositorAnimation";
158 const char* invalid_metric =
159 "Graphics.Smoothness.Jank.Main.CompositorAnimation";
161 histogram_tester.ExpectTotalCount(metric, 1u);
162 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
163 testing::ElementsAre(base::Bucket(1, 1)));
165 // Test all-sequence metrics.
166 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
167 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
168 testing::ElementsAre(base::Bucket(1, 1)));
170 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
171 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
172 testing::ElementsAre(base::Bucket(1, 1)));
174 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
176 // Stale-frame metrics
177 const char* stale_metric = "Graphics.Smoothness.Stale.CompositorAnimation";
178 const char* maxstale_metric =
179 "Graphics.Smoothness.MaxStale.CompositorAnimation";
181 histogram_tester.ExpectTotalCount(stale_metric, 3u);
183 histogram_tester.GetAllSamples(stale_metric),
184 testing::ElementsAre(base::Bucket(0, 1), base::Bucket(16, 1),
185 base::Bucket(24, 1) /*caused by +8ms fluctuation*/));
187 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
188 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
189 testing::ElementsAre(base::Bucket(24, 1)));
191 // No reporting for "Main".
192 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
195 TEST_F(JankMetricsTest, MainThreadAnimationOneJankWithNoUpdate) {
196 base::HistogramTester histogram_tester;
197 FrameSequenceTrackerType tracker_type =
198 FrameSequenceTrackerType::kMainThreadAnimation;
199 FrameInfo::SmoothEffectDrivingThread thread_type =
200 FrameInfo::SmoothEffectDrivingThread::kMain;
201 JankMetrics jank_reporter{tracker_type, thread_type};
203 // There are only 1 jank because of a no-update frame.
205 SimulateFrameSequence(&jank_reporter, {
206 /*submit */ "ab-c--D",
207 /*noupdate */ "--*----",
208 /*present */ "ab-c--D",
210 jank_reporter.ReportJankMetrics(100u);
212 // One jank is reported for "Main".
213 const char* metric = "Graphics.Smoothness.Jank.Main.MainThreadAnimation";
214 const char* invalid_metric =
215 "Graphics.Smoothness.Jank.Compositor.MainThreadAnimation";
217 histogram_tester.ExpectTotalCount(metric, 1u);
218 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
219 testing::ElementsAre(base::Bucket(1, 1)));
221 // No jank is reported for "Compositor"
222 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
224 // Test all-sequence metrics.
225 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
226 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
227 testing::ElementsAre(base::Bucket(1, 1)));
229 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
230 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
231 testing::ElementsAre(base::Bucket(1, 1)));
233 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
235 // Stale-frame metrics
236 const char* stale_metric = "Graphics.Smoothness.Stale.MainThreadAnimation";
237 const char* maxstale_metric =
238 "Graphics.Smoothness.MaxStale.MainThreadAnimation";
240 histogram_tester.ExpectTotalCount(stale_metric, 3u);
241 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
242 testing::ElementsAre(base::Bucket(0, 2), base::Bucket(33, 1)));
244 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
245 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
246 testing::ElementsAre(base::Bucket(33, 1)));
249 TEST_F(JankMetricsTest, VideoManyJanksOver300ExpectedFrames) {
250 base::HistogramTester histogram_tester;
251 FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kVideo;
252 FrameInfo::SmoothEffectDrivingThread thread_type =
253 FrameInfo::SmoothEffectDrivingThread::kCompositor;
254 JankMetrics jank_reporter{tracker_type, thread_type};
257 SimulateFrameSequence(&jank_reporter,
259 /*submit */ "ab-C--DeFGh-IJk---L---------",
260 /*noupdate */ "----------------------------",
261 /*present */ "---ab-C--De-F--Gh-I---Jk---L",
264 jank_reporter.ReportJankMetrics(300u);
266 // Report in the 7/300 ~= 2% bucket for "Compositor"
267 const char* metric = "Graphics.Smoothness.Jank.Compositor.Video";
268 const char* invalid_metric = "Graphics.Smoothness.Jank.Main.Video";
270 histogram_tester.ExpectTotalCount(metric, 1u);
271 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
272 testing::ElementsAre(base::Bucket(2, 1)));
274 // No jank is reported for "Main"
275 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
277 // Test all-sequence metrics. Videos are not counted into AllSequences.
278 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 0u);
279 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
280 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
282 // Stale-frame metrics
283 const char* stale_metric = "Graphics.Smoothness.Stale.Video";
284 const char* maxstale_metric = "Graphics.Smoothness.MaxStale.Video";
286 histogram_tester.ExpectTotalCount(stale_metric, 11u);
287 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
288 testing::ElementsAre(base::Bucket(0, 4), base::Bucket(16, 3),
289 base::Bucket(33, 2), base::Bucket(50, 2)));
291 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
292 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
293 testing::ElementsAre(base::Bucket(50, 1)));
296 TEST_F(JankMetricsTest, WheelScrollMainThreadNoJanksWithNoUpdates) {
297 base::HistogramTester histogram_tester;
298 FrameSequenceTrackerType tracker_type =
299 FrameSequenceTrackerType::kWheelScroll;
300 FrameInfo::SmoothEffectDrivingThread thread_type =
301 FrameInfo::SmoothEffectDrivingThread::kMain;
302 JankMetrics jank_reporter{tracker_type, thread_type};
304 SimulateFrameSequence(&jank_reporter,
306 /*submit */ "ab-c--d------e---------f-",
307 /*noupdate */ "--*-**-******-*********--",
308 /*present */ "---ab-c-d-----e---------f",
310 jank_reporter.ReportJankMetrics(100u);
312 // Expect 2 janks for "Main" and no jank for "Compositor"
313 const char* metric = "Graphics.Smoothness.Jank.Main.WheelScroll";
314 const char* invalid_metric =
315 "Graphics.Smoothness.Jank.Compositor.WheelScroll";
317 histogram_tester.ExpectTotalCount(metric, 1u);
318 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
319 testing::ElementsAre(base::Bucket(0, 1)));
321 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
323 // Test all-sequence metrics.
324 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
325 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
326 testing::ElementsAre(base::Bucket(0, 1)));
328 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
330 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 1u);
331 EXPECT_THAT(histogram_tester.GetAllSamples(kAllInteractionsMetricName),
332 testing::ElementsAre(base::Bucket(0, 1)));
334 // Stale-frame metrics
335 const char* stale_metric = "Graphics.Smoothness.Stale.WheelScroll";
336 const char* maxstale_metric = "Graphics.Smoothness.MaxStale.WheelScroll";
338 histogram_tester.ExpectTotalCount(stale_metric, 5u);
339 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
340 testing::ElementsAre(base::Bucket(0, 5)));
342 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
343 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
344 testing::ElementsAre(base::Bucket(0, 1)));
347 TEST_F(JankMetricsTest, WheelScrollCompositorTwoJanksWithLargeFluctuation) {
348 base::HistogramTester histogram_tester;
349 FrameSequenceTrackerType tracker_type =
350 FrameSequenceTrackerType::kWheelScroll;
351 FrameInfo::SmoothEffectDrivingThread thread_type =
352 FrameInfo::SmoothEffectDrivingThread::kCompositor;
353 JankMetrics jank_reporter{tracker_type, thread_type};
355 // Two janks; there are no no-update frames. The fluctuations in presentation
356 // of 'C' and 'D' are just big enough to cause another jank.
357 SimulateFrameSequence(&jank_reporter,
359 /*submit */ "ab-C-D",
360 /*noupdate */ "------",
361 /*present */ "ab-C-D",
363 {{'C', -2.0 /*ms*/}, {'D', +7.0 /*ms*/}});
364 jank_reporter.ReportJankMetrics(100u);
366 // One sample of 2 janks reported for "Compositor".
367 const char* metric = "Graphics.Smoothness.Jank.Compositor.WheelScroll";
368 const char* invalid_metric = "Graphics.Smoothness.Jank.Main.WheelScroll";
370 histogram_tester.ExpectTotalCount(metric, 1u);
371 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
372 testing::ElementsAre(base::Bucket(2, 1)));
374 // No reporting for "Main".
375 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
377 // Test all-sequence metrics.
378 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
379 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
380 testing::ElementsAre(base::Bucket(2, 1)));
382 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
384 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 1u);
385 EXPECT_THAT(histogram_tester.GetAllSamples(kAllInteractionsMetricName),
386 testing::ElementsAre(base::Bucket(2, 1)));
388 // Stale-frame metrics
389 const char* stale_metric = "Graphics.Smoothness.Stale.WheelScroll";
390 const char* maxstale_metric = "Graphics.Smoothness.MaxStale.WheelScroll";
392 histogram_tester.ExpectTotalCount(stale_metric, 3u);
393 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
394 testing::ElementsAre(
395 base::Bucket(0, 1), base::Bucket(14, 1), /*-2ms fluctuation*/
396 base::Bucket(25, 1) /*+7ms - (-2)ms = +9ms fluctuation*/));
398 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
399 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
400 testing::ElementsAre(base::Bucket(25, 1)));
403 TEST_F(JankMetricsTest, TouchScrollCompositorThreadManyJanksLongLatency) {
404 base::HistogramTester histogram_tester;
405 FrameSequenceTrackerType tracker_type =
406 FrameSequenceTrackerType::kTouchScroll;
407 FrameInfo::SmoothEffectDrivingThread thread_type =
408 FrameInfo::SmoothEffectDrivingThread::kCompositor;
410 JankMetrics jank_reporter{tracker_type, thread_type};
412 // There are long delays from submit to presentations.
413 SimulateFrameSequence(
416 /*submit */ "abB-c--D--EFgH----------------------",
417 /*noupdate */ "---*--------------------------------",
418 /*present */ "----------ab-B--c---D----E-----Fg--H",
420 {{'F', -3.0 /*ms*/}});
421 jank_reporter.ReportJankMetrics(120u);
423 // Expect janks in the 5/120 ~= 4% bucket for "Compositor", and no jank
425 const char* metric = "Graphics.Smoothness.Jank.Compositor.TouchScroll";
426 const char* invalid_metric = "Graphics.Smoothness.Jank.Main.TouchScroll";
428 histogram_tester.ExpectTotalCount(metric, 1u);
429 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
430 testing::ElementsAre(base::Bucket(4, 1)));
432 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
434 // Test all-sequence metrics.
435 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
436 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
437 testing::ElementsAre(base::Bucket(4, 1)));
439 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
441 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 1u);
442 EXPECT_THAT(histogram_tester.GetAllSamples(kAllInteractionsMetricName),
443 testing::ElementsAre(base::Bucket(4, 1)));
445 // Stale-frame metrics
446 const char* stale_metric = "Graphics.Smoothness.Stale.TouchScroll";
447 const char* maxstale_metric = "Graphics.Smoothness.MaxStale.TouchScroll";
449 histogram_tester.ExpectTotalCount(stale_metric, 8u);
450 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
451 testing::ElementsAre(
452 base::Bucket(0, 1), base::Bucket(3, 1), /* F to g */
453 base::Bucket(16, 2), base::Bucket(33, 1), base::Bucket(50, 1),
454 base::Bucket(66, 1), base::Bucket(80, 1) /* E to F */));
456 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
457 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
458 testing::ElementsAre(base::Bucket(80, 1)));
461 // Test if the jank reporter can correctly merge janks from another jank
463 TEST_F(JankMetricsTest, RAFMergeJanks) {
464 base::HistogramTester histogram_tester;
465 FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kRAF;
466 FrameInfo::SmoothEffectDrivingThread thread_type =
467 FrameInfo::SmoothEffectDrivingThread::kMain;
469 JankMetrics jank_reporter{tracker_type, thread_type};
470 std::unique_ptr<JankMetrics> other_reporter =
471 std::make_unique<JankMetrics>(tracker_type, thread_type);
473 std::array<std::string, 3> seqs = {
474 /*submit */ "a-b-Cd-e-F--D-",
475 /*noupdate */ "-*----*-------",
476 /*present */ "-a-b-Cd-e-F--D",
478 SimulateFrameSequence(&jank_reporter, seqs);
479 SimulateFrameSequence(other_reporter.get(), seqs);
481 jank_reporter.Merge(std::move(other_reporter));
482 EXPECT_EQ(jank_reporter.jank_count(), 6);
483 EXPECT_TRUE(jank_reporter.max_staleness() > base::Milliseconds(33) &&
484 jank_reporter.max_staleness() < base::Milliseconds(34));
485 jank_reporter.ReportJankMetrics(100u);
487 // Jank / staleness values should be reset after reporting
488 EXPECT_EQ(jank_reporter.jank_count(), 0);
489 EXPECT_EQ(jank_reporter.max_staleness(), base::Milliseconds(0));
491 // Expect 6 janks for "Main" (3 from each reporter)
492 const char* metric = "Graphics.Smoothness.Jank.Main.RAF";
493 const char* invalid_metric = "Graphics.Smoothness.Jank.Compositor.RAF";
495 histogram_tester.ExpectTotalCount(metric, 1u);
496 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
497 testing::ElementsAre(base::Bucket(6, 1)));
499 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
501 // Test all-sequence metrics.
502 // RAF is not included in AllSequences/AllAnimations metrics.
503 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 0u);
504 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
505 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
507 // Stale-frame metrics
508 const char* stale_metric = "Graphics.Smoothness.Stale.RAF";
509 const char* maxstale_metric = "Graphics.Smoothness.MaxStale.RAF";
511 histogram_tester.ExpectTotalCount(stale_metric, 12u);
512 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
513 testing::ElementsAre(base::Bucket(0, 6), base::Bucket(16, 4),
514 base::Bucket(33, 2)));
516 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
517 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
518 testing::ElementsAre(base::Bucket(33, 1)));
521 // Test if jank reporting is correctly disabled for Custom trackers.
522 TEST_F(JankMetricsTest, CustomNotReported) {
523 base::HistogramTester histogram_tester;
524 FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kCustom;
525 FrameInfo::SmoothEffectDrivingThread thread_type =
526 FrameInfo::SmoothEffectDrivingThread::kMain;
527 JankMetrics jank_reporter{tracker_type, thread_type};
529 // There should be 4 janks, but the jank reporter does not track or report
531 SimulateFrameSequence(&jank_reporter, {
532 /*submit */ "ab-C--D---E----F",
533 /*noupdate */ "----------------",
534 /*present */ "ab-C--D---E----F",
536 jank_reporter.ReportJankMetrics(100u);
538 // Expect no jank reports even though the sequence contains jank
539 histogram_tester.ExpectTotalCount("Graphics.Smoothness.Jank.Main.Custom", 0u);
540 histogram_tester.ExpectTotalCount(
541 "Graphics.Smoothness.Jank.Compositor.Custom", 0u);
543 // Test all-sequence metrics.
544 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 0u);
545 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 0u);
546 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
548 // Stale-frame metrics
549 histogram_tester.ExpectTotalCount("Graphics.Smoothness.Stale.Custom", 0u);
550 histogram_tester.ExpectTotalCount("Graphics.Smoothness.MaxStale.Custom", 0u);
553 // Test a frame sequence with a long idle period >= 100 frames.
554 // The presentation interval containing the idle period is excluded from
555 // jank/stale calculation since the length of the idle period reaches a
557 TEST_F(JankMetricsTest, CompositorAnimationOneJankWithLongIdlePeriod) {
558 base::HistogramTester histogram_tester;
559 FrameSequenceTrackerType tracker_type =
560 FrameSequenceTrackerType::kCompositorAnimation;
561 FrameInfo::SmoothEffectDrivingThread thread_type =
562 FrameInfo::SmoothEffectDrivingThread::kCompositor;
563 JankMetrics jank_reporter{tracker_type, thread_type};
565 // One jank at E. The long delay of 100 frames between b and c is considered
566 // a long idle period and therefore does not participate in jank/stale
568 SimulateFrameSequence(&jank_reporter,
570 /*submit */ std::string("a-b") +
571 std::string(100, '-') + std::string("c--d---E"),
572 /*noupdate */ std::string("---") +
573 std::string(100, '*') + std::string("--------"),
574 /*present */ std::string("a-b") +
575 std::string(100, '-') + std::string("c--d---E"),
578 jank_reporter.ReportJankMetrics(100u);
580 // One sample of 1 janks reported for "Compositor".
582 "Graphics.Smoothness.Jank.Compositor.CompositorAnimation";
583 const char* invalid_metric =
584 "Graphics.Smoothness.Jank.Main.CompositorAnimation";
586 histogram_tester.ExpectTotalCount(metric, 1u);
587 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
588 testing::ElementsAre(base::Bucket(1, 1)));
590 // Test all-sequence metrics.
591 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
592 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
593 testing::ElementsAre(base::Bucket(1, 1)));
595 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
596 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
597 testing::ElementsAre(base::Bucket(1, 1)));
599 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
601 // Stale-frame metrics
602 const char* stale_metric = "Graphics.Smoothness.Stale.CompositorAnimation";
603 const char* maxstale_metric =
604 "Graphics.Smoothness.MaxStale.CompositorAnimation";
606 histogram_tester.ExpectTotalCount(stale_metric, 4u);
608 histogram_tester.GetAllSamples(stale_metric),
609 testing::ElementsAre(base::Bucket(0, 1), /* The long frame from b to c*/
610 base::Bucket(16, 1), /* a-b */
611 base::Bucket(33, 1), /* c--d */
612 base::Bucket(50, 1)) /* d---E */);
613 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
614 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
615 testing::ElementsAre(base::Bucket(50, 1)));
617 // No reporting for "Main".
618 histogram_tester.ExpectTotalCount(invalid_metric, 0u);
621 // Test a frame sequence with an idle period < 100 frames.
622 // The jank and stale are still calculated normally in this case.
623 TEST_F(JankMetricsTest, CompositorAnimationTwoJanksWithModerateIdlePeriod) {
624 base::HistogramTester histogram_tester;
625 FrameSequenceTrackerType tracker_type =
626 FrameSequenceTrackerType::kCompositorAnimation;
627 FrameInfo::SmoothEffectDrivingThread thread_type =
628 FrameInfo::SmoothEffectDrivingThread::kCompositor;
629 JankMetrics jank_reporter{tracker_type, thread_type};
631 // Two janks at D and E. The long delay of 99 no-update frames does not
632 // exceed the capacity of the no-update frame queue and therefore is not
633 // excluded from jank/stale calculation.
634 SimulateFrameSequence(&jank_reporter,
636 /*submit */ std::string("a-b-") +
637 std::string(99, '-') + std::string("c--D---E"),
638 /*noupdate */ std::string("----") +
639 std::string(99, '*') + std::string("--------"),
640 /*present */ std::string("a-b-") +
641 std::string(99, '-') + std::string("c--D---E"),
644 jank_reporter.ReportJankMetrics(100u);
646 // One sample of 2 janks reported for "Compositor".
648 "Graphics.Smoothness.Jank.Compositor.CompositorAnimation";
649 const char* invalid_metric =
650 "Graphics.Smoothness.Jank.Main.CompositorAnimation";
652 histogram_tester.ExpectTotalCount(metric, 1u);
653 EXPECT_THAT(histogram_tester.GetAllSamples(metric),
654 testing::ElementsAre(base::Bucket(2, 1)));
656 // Test all-sequence metrics.
657 histogram_tester.ExpectTotalCount(kAllSequencesMetricName, 1u);
658 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
659 testing::ElementsAre(base::Bucket(2, 1)));
661 histogram_tester.ExpectTotalCount(kAllAnimationsMetricName, 1u);
662 EXPECT_THAT(histogram_tester.GetAllSamples(kAllSequencesMetricName),
663 testing::ElementsAre(base::Bucket(2, 1)));
665 histogram_tester.ExpectTotalCount(kAllInteractionsMetricName, 0u);
667 // Stale-frame metrics
668 const char* stale_metric = "Graphics.Smoothness.Stale.CompositorAnimation";
669 const char* maxstale_metric =
670 "Graphics.Smoothness.MaxStale.CompositorAnimation";
672 histogram_tester.ExpectTotalCount(stale_metric, 4u);
673 EXPECT_THAT(histogram_tester.GetAllSamples(stale_metric),
674 testing::ElementsAre(base::Bucket(16, 2), /* a-b & b-c */
675 base::Bucket(33, 1), /* c--d */
676 base::Bucket(50, 1)) /* d---E */);
677 histogram_tester.ExpectTotalCount(maxstale_metric, 1u);
678 EXPECT_THAT(histogram_tester.GetAllSamples(maxstale_metric),
679 testing::ElementsAre(base::Bucket(50, 1)));
681 // No reporting for "Main".
682 histogram_tester.ExpectTotalCount(invalid_metric, 0u);