Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: perf_insights/perf_insights/timeline_based_measurement/rendering_stats_test.html

Issue 1336373002: Port rendering_stats' implementation to javascript (Closed) Base URL: https://github.com/catapult-project/catapult@master
Patch Set: Address Dan's reviews Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 <!DOCTYPE HTML>
2 <!--
3 Copyright (c) 2015 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
6 -->
7
8 <link rel="import" href="/tracing/base/math.html">
9 <link rel="import" href="/tracing/base/range.html">
10 <link rel="import" href="/tracing/base/statistics.html">
11 <link rel="import" href="/tracing/base/utils.html">
12 <link rel="import" href="/tracing/core/test_utils.html">
13 <link rel="import" href="/tracing/extras/chrome/cc/constants.html">
14 <link rel="import" href="/tracing/extras/chrome/chrome_test_utils.html">
15 <link rel="import" href="/tracing/model/model.html">
16
17 <link rel="import"
18 href="/perf_insights/timeline_based_measurement/rendering_stats.html">
19
20 <script>
21 'use strict';
22
23 tr.b.unittest.testSuite(function() {
24
25 var RenderingStatsHelpers = pi.tbm.RenderingStatsHelpers;
26 var RenderingStats = pi.tbm.RenderingStats;
27 var Range = tr.b.Range;
28 var constants = tr.e.cc.constants;
29 var round = tr.b.round;
30 var flattenArray = tr.b.flattenArray;
31
32 var test_utils = tr.c.TestUtils;
33 var ThreadSlice = tr.model.ThreadSlice;
34
35
36 /**
37 * A mock timer class.
38 *
39 * An instance of this class is used as a global timer for stats and
40 * consistent timestamps for all mock trace events.
41 * The unit of time is milliseconds.
42 **/
43 function MockTimer() {
44 this.milliseconds = 0;
45 }
46
47 MockTimer.prototype = {
48 advance: function(low, high, delta) {
49 this.milliseconds += delta;
50 return delta;
51 },
52
53 advanceAndGet(opt_low, opt_high, opt_delta) {
54 if (opt_low === undefined)
55 opt_low = 0.1;
56 if (opt_high === undefined)
57 opt_high = 1.0;
58 if (opt_delta === undefined)
59 opt_delta = 0.4;
60 this.advance(opt_low, opt_high, opt_delta);
61 return this.milliseconds;
62 }
63 };
64
65 /* Stores expected data for comparison with actual RenderingStats */
66 function ReferenceRenderingStats() {
67 this.frameTimestamps = [];
68 this.frameTimes = [];
69 this.approximatedPixelPercentages = [];
70 this.checkerboardedPixelPercentages = [];
71 }
72
73 ReferenceRenderingStats.prototype = {
74 pushNewRange: function() {
75 this.frameTimestamps.push([]);
76 this.frameTimes.push([]);
77 this.approximatedPixelPercentages.push([]);
78 this.checkerboardedPixelPercentages.push([]);
79 }
80 };
81
82 /* Stores expected data for comparison with actual input latency stats */
83 function ReferenceInputLatencyStats() {
84 this.inputEventLatency = [];
85 this.input_event = [];
86 }
87
88 /**
89 * Adds a random surface flinger stats event.
90 *
91 * thread: The timeline model thread to which the event will be added.
92 * first_frame: Is this the first frame within the bounds of an action?
93 * opt_ref_stats: A ReferenceRenderingStats object to record expected
94 * values.
95 **/
96 function addSurfaceFlingerStats(
97 mock_timer, thread, first_frame, opt_ref_stats) {
98
99 // Create randonm data and timestap for impl thread rendering stats.
100 var data = {
101 'frame_count': 1,
102 'refresh_period': 16.6666
103 };
104 var timestamp = mock_timer.advanceAndGet();
105
106
107 // Add a slice with the event data to the given thread.
108 thread.sliceGroup.pushSlice(test_utils.newSliceEx({
109 type: ThreadSlice,
110 cat: 'SurfaceFlinger',
111 title: 'vsync_before',
112 start: timestamp,
113 duration: 0.0,
114 args: {
115 'data': data
116 }
117 }));
118
119
120 if (opt_ref_stats === undefined)
121 return;
122
123 // Add timestamp only if a frame was output
124 if (data['frame_count'] === 1) {
125 var frameTimes = opt_ref_stats.frameTimes;
126 var frameTimestamps = opt_ref_stats.frameTimestamps;
127 if (!first_frame) {
128 // Add frame_time if this is not the first frame in within the bounds
129 // of an action.
130 var prev_timestamps_group =
131 frameTimestamps[frameTimestamps.length - 1];
132 var prev_timestamp =
133 prev_timestamps_group[prev_timestamps_group.length - 1];
134 frameTimes[frameTimes.length - 1].push(timestamp - prev_timestamp);
135 }
136 frameTimestamps[frameTimestamps.length - 1].push(timestamp);
137
138 }
139 }
140
141 /**
142 * Adds a random display rendering stats event.
143 *
144 * thread: The timeline model thread to which the event will be added.
145 * first_frame: Is this the first frame within the bounds of an action?
146 * ref_stats: A ReferenceRenderingStats object to record expected values.
147 **/
148 function addDisplayRenderingStats(
149 mock_timer, thread, first_frame, opt_ref_stats) {
150
151 // Create randonm data and timestap for main thread rendering stats.
152 var data = {
153 'frame_count': 1
154 };
155 var timestamp = mock_timer.advanceAndGet();
156
157 // Add a slice with the event data to the given thread.
158 thread.sliceGroup.pushSlice(test_utils.newSliceEx({
159 type: ThreadSlice,
160 cat: 'benchmark',
161 title: 'BenchmarkInstrumentation::DisplayRenderingStats',
162 start: timestamp,
163 duration: 0.0,
164 args: {
165 'data': data
166 }
167 }));
168
169 if (opt_ref_stats === undefined)
170 return;
171 var frameTimes = opt_ref_stats.frameTimes;
172 var frameTimestamps = opt_ref_stats.frameTimestamps;
173 // Add timestamp only if a frame was output
174 if (!first_frame) {
175 // Add frame_time if this is not the first frame in within the bounds of
176 // an action.
177 var prev_timestamps_group =
178 frameTimestamps[frameTimestamps.length - 1];
179 var prev_timestamp =
180 prev_timestamps_group[prev_timestamps_group.length - 1];
181 frameTimes[frameTimes.length - 1].push(timestamp - prev_timestamp);
182 }
183 frameTimestamps[frameTimestamps.length - 1].push(timestamp);
184 }
185
186 /**
187 * Adds a random impl thread rendering stats event.
188 *
189 * thread: The model thread to which the event will be added.
190 * first_frame: Is this the first frame within the bounds of an action?
191 * opt_ref_stats: A ReferenceRenderingStats object to record expected
192 * values.
193 **/
194 function addImplThreadRenderingStats(
195 mock_timer, thread, first_frame, opt_ref_stats) {
196
197 // Create randonm data and timestap for impl thread rendering stats.
198 var data = {
199 'frame_count': 1,
200 'visible_content_area': 95,
201 'approximated_visible_content_area': 3,
202 'checkerboarded_visible_content_area': 4
203 };
204 var timestamp = mock_timer.advanceAndGet();
205
206 // Add a slice with the event data to the given thread.
207 thread.sliceGroup.pushSlice(test_utils.newSliceEx({
208 type: ThreadSlice,
209 cat: 'benchmark',
210 title: 'BenchmarkInstrumentation::ImplThreadRenderingStats',
211 start: timestamp,
212 duration: 0.0,
213 args: {
214 'data': data
215 }
216 }));
217
218 if (!opt_ref_stats)
219 return;
220
221 // Add timestamp only if a frame was output
222 if (data['frame_count'] === 1) {
223 if (!first_frame) {
224 // Add frame_time if this is not the first frame in within the bounds
225 // of an action.
226 var lastFrameTimestamps = opt_ref_stats.frameTimestamps[
227 opt_ref_stats.frameTimestamps.length - 1];
228 var prev_timestamp = lastFrameTimestamps[
229 lastFrameTimestamps.length - 1];
230 opt_ref_stats.frameTimes[opt_ref_stats.frameTimes.length - 1].push(
231 timestamp - prev_timestamp);
232 }
233 opt_ref_stats.frameTimestamps[
234 opt_ref_stats.frameTimestamps.length - 1].push(timestamp);
235
236 opt_ref_stats.approximatedPixelPercentages[
237 opt_ref_stats.approximatedPixelPercentages.length - 1].push(
238 round(tr.b.Statistics.divideIfPossibleOrZero(
239 data['approximated_visible_content_area'],
240 data['visible_content_area']) * 100.0, 3));
241
242 opt_ref_stats.checkerboardedPixelPercentages[
243 opt_ref_stats.checkerboardedPixelPercentages.length - 1].push(
244 round(tr.b.Statistics.divideIfPossibleOrZero(
245 data['checkerboarded_visible_content_area'],
246 data['visible_content_area']) * 100.0, 3));
247 }
248 }
249
250 /**
251 * Adds a random input latency stats event.
252 *
253 * start_thread: The start thread on which the async slice is added.
254 * end_thread: The end thread on which the async slice is ended.
255 * opt_ref_latency_stats: A ReferenceInputLatencyStats object for expected
256 * values.
257 **/
258 function addInputLatencyStats(
259 mock_timer, start_thread, end_thread, opt_ref_latency_stats) {
260
261 var original_comp_time = mock_timer.advanceAndGet(2, 4) * 1000.0;
262 var ui_comp_time = mock_timer.advanceAndGet(2, 4) * 1000.0;
263 var begin_comp_time = mock_timer.advanceAndGet(2, 4) * 1000.0;
264 var forward_comp_time = mock_timer.advanceAndGet(2, 4) * 1000.0;
265 var end_comp_time = mock_timer.advanceAndGet(10, 20) * 1000.0;
266
267 var data = {};
268 data[constants.ORIGINAL_COMP_NAME] = {
269 'time': original_comp_time
270 };
271 data[constants.UI_COMP_NAME] = {
272 'time': ui_comp_time
273 };
274 data[constants.BEGIN_COMP_NAME] = {
275 'time': begin_comp_time
276 };
277 data[constants.END_COMP_NAME] = {
278 'time': end_comp_time
279 };
280
281 var timestamp = mock_timer.advanceAndGet(2, 4);
282
283 var tracing_async_slice = test_utils.newAsyncSliceEx({
284 cat: 'benchmark',
285 title: 'InputLatency',
286 start: timestamp,
287 duration: 0
288 });
289
290 var async_sub_slice = test_utils.newAsyncSliceEx({
291 cat: 'benchmark',
292 title: constants.GESTURE_SCROLL_UPDATE_EVENT_NAME,
293 start: timestamp,
294 args: {
295 'data': data
296 },
297 duration: 0
298 });
299 async_sub_slice.parentContainer = tracing_async_slice;
300 async_sub_slice.startThread = start_thread;
301 async_sub_slice.endThread = end_thread;
302
303 tracing_async_slice.subSlices.push(async_sub_slice);
304 tracing_async_slice.startThread = start_thread;
305 tracing_async_slice.endThread = end_thread;
306 start_thread.sliceGroup.pushSlice(tracing_async_slice);
307
308 // Add scroll update latency info.
309 var scroll_update_data = {};
310 scroll_update_data[
311 constants.BEGIN_SCROLL_UPDATE_COMP_NAME] = {
312 'time': begin_comp_time
313 };
314 scroll_update_data[
315 constants.FORWARD_SCROLL_UPDATE_COMP_NAME] = {
316 'time': forward_comp_time
317 };
318 scroll_update_data[constants.END_COMP_NAME] = {
319 'time': end_comp_time
320 };
321
322 var scroll_async_slice = test_utils.newAsyncSliceEx({
323 cat: 'benchmark',
324 title: 'InputLatency',
325 start: timestamp,
326 duration: 0
327 });
328
329 var scroll_async_sub_slice = test_utils.newAsyncSliceEx({
330 cat: 'benchmark',
331 title: constants.SCROLL_UPDATE_EVENT_NAME,
332 start: timestamp,
333 args: {
334 'data': scroll_update_data
335 },
336 duration: 0
337 });
338 scroll_async_sub_slice.parentContainer = scroll_async_slice;
339 scroll_async_sub_slice.startThread = start_thread;
340 scroll_async_sub_slice.endThread = end_thread;
341
342 scroll_async_slice.subSlices.push(scroll_async_sub_slice);
343 scroll_async_slice.startThread = start_thread;
344 scroll_async_slice.endThread = end_thread;
345 start_thread.sliceGroup.pushSlice(scroll_async_slice);
346
347 // Also add some dummy frame statistics so we can feed the resulting
348 // timeline to RenderingStats.
349 addImplThreadRenderingStats(mock_timer, end_thread, false);
350
351 if (opt_ref_latency_stats === undefined)
352 return;
353
354 opt_ref_latency_stats.input_event.push(async_sub_slice);
355 opt_ref_latency_stats.input_event.push(
356 scroll_async_sub_slice);
357 opt_ref_latency_stats.inputEventLatency.push({
358 eventTitle: constants.GESTURE_SCROLL_UPDATE_EVENT_NAME,
359 latency: (data[constants.END_COMP_NAME]['time'] -
360 data[constants.ORIGINAL_COMP_NAME]['time']) / 1000.0
361 });
362 var scroll_update_time = (
363 scroll_update_data[constants.END_COMP_NAME].time -
364 scroll_update_data[
365 constants.BEGIN_SCROLL_UPDATE_COMP_NAME].time);
366 opt_ref_latency_stats.inputEventLatency.push({
367 eventTitle: constants.SCROLL_UPDATE_EVENT_NAME,
368 latency: scroll_update_time / 1000.0
369 });
370 };
371
372 test('hasRenderingStats', function() {
373 var model = new tr.Model();
374 var timer = new MockTimer();
375
376 // A process without rendering stats
377 var process_without_stats = model.getOrCreateProcess(1);
378 var thread_without_stats = process_without_stats.getOrCreateThread(
379 11);
380 model.updateBounds();
381 assert.equal(
382 RenderingStatsHelpers.hasRenderingStats(thread_without_stats),
383 false);
384
385 // A process with rendering stats, but no frames in them
386 var process_without_frames = model.getOrCreateProcess(2);
387 var thread_without_frames = process_without_frames.getOrCreateThread(
388 21);
389 process_without_frames.updateBounds();
390 assert.equal(
391 RenderingStatsHelpers.hasRenderingStats(thread_without_frames),
392 false);
393
394 // A process with rendering stats and frames in them
395 var process_with_frames = model.getOrCreateProcess(3);
396 var thread_with_frames = process_with_frames.getOrCreateThread(31);
397 addImplThreadRenderingStats(timer, thread_with_frames, true);
398 process_with_frames.updateBounds();
399 assert.equal(
400 RenderingStatsHelpers.hasRenderingStats(thread_with_frames),
401 true);
402
403 });
404
405 test('bothSurfaceFlingerAndDisplayStats', function() {
406 var model = new tr.Model();
407 var timer = new MockTimer();
408
409 var ref_stats = new ReferenceRenderingStats();
410 ref_stats.pushNewRange();
411 var surface_flinger = model.getOrCreateProcess(4);
412 surface_flinger.title = 'SurfaceFlinger';
413 var surface_flinger_thread = surface_flinger.getOrCreateThread(41);
414 var renderer = model.getOrCreateProcess(2);
415 var browser = model.getOrCreateProcess(3);
416 var browser_main = browser.getOrCreateThread(31);
417 browser_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
418 timer.advanceAndGet(2, 4), '');
419
420 // Create SurfaceFlinger stats and display rendering stats.
421 for (var i = 0; i < 10; i++) {
422 var first = i === 0;
423 addSurfaceFlingerStats(timer, surface_flinger_thread, first,
424 ref_stats);
425 timer.advance(2, 4, 0.5);
426 }
427
428 for (var i = 0; i < 10; i++) {
429 var first = i === 0;
430 addDisplayRenderingStats(timer, browser_main, first);
431 timer.advance(5, 10, 0.1);
432 }
433
434 browser_main.sliceGroup.endSlice(timer.advanceAndGet());
435 timer.advance(2, 4, 0.2);
436
437 browser.updateBounds();
438 renderer.updateBounds();
439 var timelineRanges = [];
440 model.iterateAllEvents(function(event) {
441 if (event.title === 'ActionA') {
442 timelineRanges.push(Range.fromExplicitRange(event.start, event.end));
443 }
444 });
445 var stats = new RenderingStats(
446 renderer, browser, surface_flinger, timelineRanges);
447
448 // Compare rendering stats to reference - Only SurfaceFlinger stats should
449 // count
450 assert.deepEqual(stats.frameTimestamps, ref_stats.frameTimestamps);
451 assert.deepEqual(stats.frameTimes, ref_stats.frameTimes);
452 });
453
454 test('bothDisplayAndImplStats', function() {
455 var model = new tr.Model();
456 var timer = new MockTimer();
457
458 var ref_stats = new ReferenceRenderingStats();
459 ref_stats.pushNewRange();
460 var renderer = model.getOrCreateProcess(2);
461 var browser = model.getOrCreateProcess(3);
462 var browser_main = browser.getOrCreateThread(31);
463 browser_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
464 timer.advanceAndGet(2, 4), '');
465
466 // Create SurfaceFlinger stats and display rendering stats.
467 for (var i = 0; i < 10; i++) {
468 var first = i === 0;
469 addImplThreadRenderingStats(timer, browser_main, first);
470 timer.advance(2, 4, 0.4);
471 }
472
473 for (var i = 0; i < 10; i++) {
474 var first = i === 0;
475 addDisplayRenderingStats(timer, browser_main, first, ref_stats);
476 timer.advance(5, 10, 0.3);
477 }
478
479 browser_main.sliceGroup.endSlice(timer.advanceAndGet());
480 timer.advance(2, 4, 0.9);
481
482 browser.updateBounds();
483 renderer.updateBounds();
484 var timelineRanges = [];
485 model.iterateAllEvents(function(event) {
486 if (event.title === 'ActionA') {
487 timelineRanges.push(Range.fromExplicitRange(event.start, event.end));
488 }
489 });
490 var stats = new RenderingStats(renderer, browser, null, timelineRanges);
491
492 // Compare rendering stats to reference - Only SurfaceFlinger stats should
493 // count
494 assert.deepEqual(stats.frameTimestamps, ref_stats.frameTimestamps);
495 assert.deepEqual(stats.frameTimes, ref_stats.frameTimes);
496 });
497
498
499 test('rangeWithoutFrames', function() {
500 var model = new tr.Model();
501 var timer = new MockTimer();
502
503 // Create a renderer process, with a main thread and impl thread.
504 var renderer = model.getOrCreateProcess(2);
505 var renderer_main = renderer.getOrCreateThread(21);
506 var renderer_compositor = renderer.getOrCreateThread(22);
507
508 // Create 10 main and impl rendering stats events for Action A.
509 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
510 timer.advanceAndGet(2, 4), '');
511 for (var i = 0; i < 10; i++) {
512 var first = i === 0;
513 addImplThreadRenderingStats(timer, renderer_compositor, first);
514 }
515 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
516 timer.advance(2, 4, 0.7);
517
518 // Create 5 main and impl rendering stats events not within any action.
519 for (var i = 0; i < 5; i++) {
520 var first = i === 0;
521 addImplThreadRenderingStats(timer, renderer_compositor, first);
522 }
523
524 // Create Action B without any frames. This should trigger
525 // NotEnoughFramesError when the RenderingStats object is created.
526 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionB',
527 timer.advanceAndGet(2, 4), '');
528
529 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
530
531 renderer.updateBounds();
532 var timelineRanges = [];
533 model.iterateAllEvents(function(event) {
534 if (event.title === 'ActionA' || event.title === 'ActionB') {
535 timelineRanges.push(Range.fromExplicitRange(event.start, event.end));
536 }
537 });
538 var stats = new RenderingStats(
539 renderer, null, null, timelineRanges);
540
541 assert.equal(0, stats.frameTimestamps[1].length);
542 });
543
544 test('fromTimeline', function() {
545 var model = new tr.Model();
546
547 // Create a browser process and a renderer process, and a main thread and
548 // impl thread for each.
549 var browser = model.getOrCreateProcess(1);
550 var browser_compositor = browser.getOrCreateThread(12);
551 var renderer = model.getOrCreateProcess(2);
552 var renderer_main = renderer.getOrCreateThread(21);
553 var renderer_compositor = renderer.getOrCreateThread(22);
554
555 var timer = new MockTimer();
556 var renderer_ref_stats = new ReferenceRenderingStats();
557 var browser_ref_stats = new ReferenceRenderingStats();
558
559 // Create 10 main and impl rendering stats events for Action A.
560 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
561 timer.advanceAndGet(2, 4), '');
562 renderer_ref_stats.pushNewRange();
563 browser_ref_stats.pushNewRange();
564 for (var i = 0; i < 10; i++) {
565 var first = i === 0;
566 addImplThreadRenderingStats(
567 timer, renderer_compositor, first, renderer_ref_stats);
568 addImplThreadRenderingStats(
569 timer, browser_compositor, first, browser_ref_stats);
570 }
571 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
572
573 // Create 5 main and impl rendering stats events not within any action.
574 for (var i = 0; i < 5; i++) {
575 var first = i === 0;
576 addImplThreadRenderingStats(timer, renderer_compositor, first);
577 addImplThreadRenderingStats(timer, browser_compositor, first);
578 }
579
580 // Create 10 main and impl rendering stats events for Action B.
581 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionB',
582 timer.advanceAndGet(2, 4), '');
583 renderer_ref_stats.pushNewRange();
584 browser_ref_stats.pushNewRange();
585 for (var i = 0; i < 10; i++) {
586 var first = i === 0;
587 addImplThreadRenderingStats(
588 timer, renderer_compositor, first, renderer_ref_stats);
589 addImplThreadRenderingStats(
590 timer, browser_compositor, first, browser_ref_stats);
591 }
592 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
593
594 // Create 10 main and impl rendering stats events for Action A.
595 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
596 timer.advanceAndGet(2, 4), '');
597 renderer_ref_stats.pushNewRange();
598 browser_ref_stats.pushNewRange();
599 for (var i = 0; i < 10; i++) {
600 var first = i === 0;
601 addImplThreadRenderingStats(
602 timer, renderer_compositor, first, renderer_ref_stats);
603 addImplThreadRenderingStats(
604 timer, browser_compositor, first, browser_ref_stats);
605 }
606 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
607 timer.advance(2, 4, 0.1);
608
609 browser.updateBounds();
610 renderer.updateBounds();
611 var timelineRanges = [];
612 model.iterateAllEvents(function(event) {
613 if (event.title === 'ActionA' || event.title === 'ActionB') {
614 timelineRanges.push(Range.fromExplicitRange(event.start, event.end));
615 }
616 });
617 var stats = new RenderingStats(
618 renderer, browser, null, timelineRanges);
619
620 // Compare rendering stats to reference.
621 assert.deepEqual(stats.frameTimestamps,
622 browser_ref_stats.frameTimestamps);
623 assert.deepEqual(stats.frameTimes,
624 browser_ref_stats.frameTimes);
625 assert.deepEqual(stats.approximatedPixelPercentages,
626 renderer_ref_stats.approximatedPixelPercentages);
627 assert.deepEqual(stats.checkerboardedPixelPercentages,
628 renderer_ref_stats.checkerboardedPixelPercentages);
629 });
630
631 test('inputLatencyFromTimeline', function() {
632 var model = new tr.Model();
633
634 // Create a browser process and a renderer process.
635 var browser = model.getOrCreateProcess(1);
636 var browser_main = browser.getOrCreateThread(11);
637 var renderer = model.getOrCreateProcess(2);
638 var renderer_main = renderer.getOrCreateThread(21);
639
640 var timer = new MockTimer();
641 var ref_latency = new ReferenceInputLatencyStats();
642
643 // Create 10 input latency stats events for Action A.
644 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
645 timer.advanceAndGet(2, 4), '');
646 for (var i = 0; i < 10; i++) {
647 addInputLatencyStats(timer, browser_main, renderer_main, ref_latency);
648 }
649 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
650
651 // Create 5 input latency stats events not within any action.
652 timer.advance(2, 4, 0.3);
653 for (var i = 0; i < 5; i++) {
654 addInputLatencyStats(timer, browser_main, renderer_main);
655 }
656
657 // Create 10 input latency stats events for Action B.
658 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionB',
659 timer.advanceAndGet(2, 4), '');
660 for (var i = 0; i < 10; i++) {
661 addInputLatencyStats(timer, browser_main, renderer_main, ref_latency);
662 }
663 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
664
665 // Create 10 input latency stats events for Action A.
666 renderer_main.sliceGroup.beginSlice('webkit.console', 'ActionA',
667 timer.advanceAndGet(2, 4), '');
668 for (var i = 0; i < 10; i++) {
669 addInputLatencyStats(timer, browser_main, renderer_main, ref_latency);
670 }
671 renderer_main.sliceGroup.endSlice(timer.advanceAndGet(2, 4));
672
673 browser.updateBounds();
674 renderer.updateBounds();
675
676 var latencyEvents = [];
677 var timelineRanges = [];
678 model.iterateAllEvents(function(event) {
679 if (event.title === 'ActionA' || event.title === 'ActionB') {
680 var range = Range.fromExplicitRange(event.start, event.end);
681 timelineRanges.push(range);
682 latencyEvents.push.apply(
683 latencyEvents,
684 RenderingStatsHelpers.getLatencyEvents(browser, range));
685 }
686 });
687 assert.deepEqual(latencyEvents, ref_latency.input_event);
688
689 var stats = new RenderingStats(renderer, browser, null, timelineRanges);
690
691 var expected_input_latency = ref_latency.inputEventLatency.filter(
692 function(e) {
693 return (e.eventTitle !==
694 constants.SCROLL_UPDATE_EVENT_NAME);
695 }).map(
696 function(e) {
697 return e.latency;
698 }
699 );
700 assert.deepEqual(
701 flattenArray(stats.inputEventLatency),
702 expected_input_latency);
703 var expected_scroll_latency = ref_latency.inputEventLatency.filter(
704 function(e) {
705 return (e.eventTitle ===
706 constants.SCROLL_UPDATE_EVENT_NAME);
707 }).map(
708 function(e) {
709 return e.latency;
710 }
711 );
712
713 assert.deepEqual(
714 flattenArray(stats.scrollUpdateLatency),
715 expected_scroll_latency);
716
717 var expected_gestureScrollUpdateLatency =
718 ref_latency.inputEventLatency.filter(
719 function(e) {
720 return (e.eventTitle ===
721 constants.GESTURE_SCROLL_UPDATE_EVENT_NAME);
722 }).map(
723 function(e) {
724 return e.latency;
725 }
726 );
727
728 assert.deepEqual(
729 flattenArray(stats.gestureScrollUpdateLatency),
730 expected_gestureScrollUpdateLatency);
731 });
732
733 });
734 </script>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698