1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 from telemetry
.page
import page
as page_module
5 from telemetry
.page
import page_set
as page_set_module
8 class ToughSchedulingCasesPage(page_module
.Page
):
10 def __init__(self
, url
, page_set
):
11 super(ToughSchedulingCasesPage
, self
).__init
__(
12 url
=url
, page_set
=page_set
, credentials_path
='data/credentials.json')
13 self
.user_agent_type
= 'mobile'
14 self
.archive_data_file
= 'data/tough_scheduling_cases.json'
16 def RunPageInteractions(self
, action_runner
):
17 with action_runner
.CreateGestureInteraction('ScrollAction'):
18 action_runner
.ScrollPage()
21 class Page1(ToughSchedulingCasesPage
):
23 """Why: Simulate oversubscribed main thread."""
25 def __init__(self
, page_set
):
26 super(Page1
, self
).__init
__(
27 url
='file://tough_scheduling_cases/simple_text_page.html?main_busy',
30 self
.synthetic_delays
= {'cc.BeginMainFrame': {'target_duration': 0.008}}
33 class Page2(ToughSchedulingCasesPage
):
35 """Why: Simulate oversubscribed main thread."""
37 def __init__(self
, page_set
):
38 super(Page2
, self
).__init
__(
39 # pylint: disable=C0301
40 url
='file://tough_scheduling_cases/simple_text_page.html?main_very_busy',
43 self
.synthetic_delays
= {'cc.BeginMainFrame': {'target_duration': 0.024}}
46 class Page3(ToughSchedulingCasesPage
):
48 """Why: Simulate a page with a a few graphics layers."""
50 def __init__(self
, page_set
):
51 super(Page3
, self
).__init
__(
52 # pylint: disable=C0301
53 url
='file://tough_scheduling_cases/simple_text_page.html?medium_layers',
56 self
.synthetic_delays
= {
57 'cc.DrawAndSwap': {'target_duration': 0.004},
58 'gpu.PresentingFrame': {'target_duration': 0.004},
59 'cc.BeginMainFrame': {'target_duration': 0.004}
63 class Page4(ToughSchedulingCasesPage
):
65 """Why: Simulate a page with many graphics layers."""
67 def __init__(self
, page_set
):
68 super(Page4
, self
).__init
__(
69 # pylint: disable=C0301
70 url
='file://tough_scheduling_cases/simple_text_page.html?many_layers',
73 self
.synthetic_delays
= {
74 'cc.DrawAndSwap': {'target_duration': 0.012},
75 'gpu.PresentingFrame': {'target_duration': 0.012},
76 'cc.BeginMainFrame': {'target_duration': 0.012}
80 class Page5(ToughSchedulingCasesPage
):
82 """Why: Simulate a page with expensive recording and rasterization."""
84 def __init__(self
, page_set
):
85 super(Page5
, self
).__init
__(
86 # pylint: disable=C0301
87 url
='file://tough_scheduling_cases/simple_text_page.html?medium_raster',
90 self
.synthetic_delays
= {
91 'cc.RasterRequiredForActivation': {'target_duration': 0.004},
92 'cc.BeginMainFrame': {'target_duration': 0.004},
93 'gpu.AsyncTexImage': {'target_duration': 0.004}
97 class Page6(ToughSchedulingCasesPage
):
99 """Why: Simulate a page with expensive recording and rasterization."""
101 def __init__(self
, page_set
):
102 super(Page6
, self
).__init
__(
103 # pylint: disable=C0301
104 url
='file://tough_scheduling_cases/simple_text_page.html?heavy_raster',
107 self
.synthetic_delays
= {
108 'cc.RasterRequiredForActivation': {'target_duration': 0.024},
109 'cc.BeginMainFrame': {'target_duration': 0.024},
110 'gpu.AsyncTexImage': {'target_duration': 0.024}
114 class Page7(ToughSchedulingCasesPage
):
116 """Why: Medium cost touch handler."""
118 def __init__(self
, page_set
):
119 super(Page7
, self
).__init
__(
120 # pylint: disable=C0301
121 url
='file://tough_scheduling_cases/touch_handler_scrolling.html?medium_handler',
124 self
.synthetic_delays
= {'blink.HandleInputEvent':
125 {'target_duration': 0.008}}
128 class Page8(ToughSchedulingCasesPage
):
130 """Why: Slow touch handler."""
132 def __init__(self
, page_set
):
133 super(Page8
, self
).__init
__(
134 # pylint: disable=C0301
135 url
='file://tough_scheduling_cases/touch_handler_scrolling.html?slow_handler',
138 self
.synthetic_delays
= {'blink.HandleInputEvent':
139 {'target_duration': 0.024}}
142 class Page9(ToughSchedulingCasesPage
):
144 """Why: Touch handler that often takes a long time."""
146 def __init__(self
, page_set
):
147 super(Page9
, self
).__init
__(
148 # pylint: disable=C0301
149 url
='file://tough_scheduling_cases/touch_handler_scrolling.html?janky_handler',
152 self
.synthetic_delays
= {'blink.HandleInputEvent':
153 {'target_duration': 0.024, 'mode': 'alternating'}
157 class Page10(ToughSchedulingCasesPage
):
159 """Why: Touch handler that occasionally takes a long time."""
161 def __init__(self
, page_set
):
162 super(Page10
, self
).__init
__(
163 # pylint: disable=C0301
164 url
='file://tough_scheduling_cases/touch_handler_scrolling.html?occasionally_janky_handler',
167 self
.synthetic_delays
= {'blink.HandleInputEvent':
168 {'target_duration': 0.024, 'mode': 'oneshot'}}
171 class Page11(ToughSchedulingCasesPage
):
173 """Why: Super expensive touch handler causes browser to scroll after a
176 def __init__(self
, page_set
):
177 super(Page11
, self
).__init
__(
178 # pylint: disable=C0301
179 url
='file://tough_scheduling_cases/touch_handler_scrolling.html?super_slow_handler',
182 self
.synthetic_delays
= {'blink.HandleInputEvent':
183 {'target_duration': 0.2}}
186 class Page12(ToughSchedulingCasesPage
):
188 """Why: Super expensive touch handler that only occupies a part of the page.
191 def __init__(self
, page_set
):
192 super(Page12
, self
).__init
__(
193 url
='file://tough_scheduling_cases/div_touch_handler.html',
196 self
.synthetic_delays
= {'blink.HandleInputEvent': {'target_duration': 0.2}}
199 class Page13(ToughSchedulingCasesPage
):
201 """Why: Test a moderately heavy requestAnimationFrame handler."""
203 def __init__(self
, page_set
):
204 super(Page13
, self
).__init
__(
205 url
='file://tough_scheduling_cases/raf.html?medium_handler',
208 self
.synthetic_delays
= {
209 'cc.RasterRequiredForActivation': {'target_duration': 0.004},
210 'cc.BeginMainFrame': {'target_duration': 0.004},
211 'gpu.AsyncTexImage': {'target_duration': 0.004}
215 class Page14(ToughSchedulingCasesPage
):
217 """Why: Test a moderately heavy requestAnimationFrame handler."""
219 def __init__(self
, page_set
):
220 super(Page14
, self
).__init
__(
221 url
='file://tough_scheduling_cases/raf.html?heavy_handler',
224 self
.synthetic_delays
= {
225 'cc.RasterRequiredForActivation': {'target_duration': 0.024},
226 'cc.BeginMainFrame': {'target_duration': 0.024},
227 'gpu.AsyncTexImage': {'target_duration': 0.024}
231 class Page15(ToughSchedulingCasesPage
):
233 """Why: Simulate a heavily GPU bound page."""
235 def __init__(self
, page_set
):
236 super(Page15
, self
).__init
__(
237 url
='file://tough_scheduling_cases/raf.html?gpu_bound',
240 self
.synthetic_delays
= {'gpu.PresentingFrame': {'target_duration': 0.1}}
243 class Page16(ToughSchedulingCasesPage
):
245 """Why: Test a requestAnimationFrame handler with a heavy first frame."""
247 def __init__(self
, page_set
):
248 super(Page16
, self
).__init
__(
249 url
='file://tough_scheduling_cases/raf.html?heavy_first_frame',
252 self
.synthetic_delays
= {'cc.BeginMainFrame': {'target_duration': 0.15,
256 class Page17(ToughSchedulingCasesPage
):
258 """Why: Medium stress test for the scheduler."""
260 def __init__(self
, page_set
):
261 super(Page17
, self
).__init
__(
262 url
='file://tough_scheduling_cases/raf_touch_animation.html?medium',
265 self
.synthetic_delays
= {
266 'cc.DrawAndSwap': {'target_duration': 0.004},
267 'cc.BeginMainFrame': {'target_duration': 0.004}
271 class Page18(ToughSchedulingCasesPage
):
273 """Why: Heavy stress test for the scheduler."""
275 def __init__(self
, page_set
):
276 super(Page18
, self
).__init
__(
277 url
='file://tough_scheduling_cases/raf_touch_animation.html?heavy',
280 self
.synthetic_delays
= {
281 'cc.DrawAndSwap': {'target_duration': 0.012},
282 'cc.BeginMainFrame': {'target_duration': 0.012}
286 class Page19(ToughSchedulingCasesPage
):
288 """Why: Both main and impl thread animating concurrently."""
290 def __init__(self
, page_set
):
291 super(Page19
, self
).__init
__(
292 url
='file://tough_scheduling_cases/split_animation.html',
295 def RunPageInteractions(self
, action_runner
):
296 with action_runner
.CreateInteraction('SplitAnimation'):
297 action_runner
.Wait(3)
300 class Page20(ToughSchedulingCasesPage
):
302 """Why: Simple JS touch dragging."""
304 def __init__(self
, page_set
):
305 super(Page20
, self
).__init
__(
306 url
='file://tough_scheduling_cases/simple_touch_drag.html',
309 def RunPageInteractions(self
, action_runner
):
310 with action_runner
.CreateGestureInteraction('ScrollAction'):
311 action_runner
.ScrollElement(
315 speed_in_pixels_per_second
=150,
319 class EmptyTouchHandlerPage(ToughSchedulingCasesPage
):
321 """Why: Scrolling on a page with a touch handler that consumes no events but
324 def __init__(self
, name
, desktop
, slow_handler
, bounce
, page_set
):
325 super(EmptyTouchHandlerPage
, self
).__init
__(
326 url
='file://tough_scheduling_cases/empty_touch_handler' +
327 ('_desktop' if desktop
else '') + '.html?' + name
,
331 self
.synthetic_delays
= {
332 'blink.HandleInputEvent': {'target_duration': 0.2}
337 def RunPageInteractions(self
, action_runner
):
339 with action_runner
.CreateGestureInteraction('ScrollBounceAction'):
340 action_runner
.ScrollBouncePage()
342 with action_runner
.CreateGestureInteraction('ScrollAction'):
343 # Speed and distance are tuned to run exactly as long as a scroll
345 action_runner
.ScrollPage(use_touch
=True, speed_in_pixels_per_second
=400,
349 class SynchronizedScrollOffsetPage(ToughSchedulingCasesPage
):
351 """Why: For measuring the latency of scroll-synchronized effects."""
353 def __init__(self
, page_set
):
354 super(SynchronizedScrollOffsetPage
, self
).__init
__(
355 url
='file://tough_scheduling_cases/sync_scroll_offset.html',
358 def RunPageInteractions(self
, action_runner
):
359 with action_runner
.CreateGestureInteraction('ScrollBounceAction'):
360 action_runner
.ScrollBouncePage()
363 class SecondBatchJsPage(ToughSchedulingCasesPage
):
365 """Why: For testing dynamically loading a large batch of Javascript and
366 running a part of it in response to user input.
369 def __init__(self
, page_set
, variant
='medium'):
370 super(SecondBatchJsPage
, self
).__init
__(
371 url
='file://tough_scheduling_cases/second_batch_js.html?%s' % variant
,
374 def RunPageInteractions(self
, action_runner
):
375 # Do a dummy tap to warm up the synthetic tap code path.
376 action_runner
.TapElement(selector
='div[id="spinner"]')
377 # Begin the action immediately because we want the page to update smoothly
378 # even while resources are being loaded.
379 action_runner
.WaitForJavaScriptCondition('window.__ready !== undefined')
381 with action_runner
.CreateGestureInteraction('LoadAction'):
382 action_runner
.ExecuteJavaScript('kickOffLoading()')
383 action_runner
.WaitForJavaScriptCondition('window.__ready')
384 # Click one second after the resources have finished loading.
385 action_runner
.Wait(1)
386 action_runner
.TapElement(selector
='input[id="run"]')
387 # Wait for the test to complete.
388 action_runner
.WaitForJavaScriptCondition('window.__finished')
391 class ToughSchedulingCasesPageSet(page_set_module
.PageSet
):
393 """Tough scheduler latency test cases."""
396 super(ToughSchedulingCasesPageSet
, self
).__init
__(
397 user_agent_type
='mobile',
398 archive_data_file
='data/tough_scheduling_cases.json',
399 bucket
=page_set_module
.INTERNAL_BUCKET
)
401 # Why: Simple scrolling baseline
402 self
.AddUserStory(ToughSchedulingCasesPage(
403 'file://tough_scheduling_cases/simple_text_page.html',
405 self
.AddUserStory(Page1(self
))
406 self
.AddUserStory(Page2(self
))
407 self
.AddUserStory(Page3(self
))
408 self
.AddUserStory(Page4(self
))
409 # Disabled until crbug.com/413829 is fixed.
410 # self.AddUserStory(Page5(self))
411 # Disabled because of crbug.com/413829 and flakiness crbug.com/368532
412 # self.AddUserStory(Page6(self))
413 # Why: Touch handler scrolling baseline
414 self
.AddUserStory(ToughSchedulingCasesPage(
415 'file://tough_scheduling_cases/touch_handler_scrolling.html',
417 self
.AddUserStory(Page7(self
))
418 self
.AddUserStory(Page8(self
))
419 self
.AddUserStory(Page9(self
))
420 self
.AddUserStory(Page10(self
))
421 self
.AddUserStory(Page11(self
))
422 self
.AddUserStory(Page12(self
))
423 # Why: requestAnimationFrame scrolling baseline
424 self
.AddUserStory(ToughSchedulingCasesPage(
425 'file://tough_scheduling_cases/raf.html',
427 # Why: Test canvas blocking behavior
428 self
.AddUserStory(ToughSchedulingCasesPage(
429 'file://tough_scheduling_cases/raf_canvas.html',
431 # Disabled until crbug.com/413829 is fixed.
432 # self.AddUserStory(Page13(self))
433 # Disabled because of crbug.com/413829 and flakiness crbug.com/368532
434 # self.AddUserStory(Page14(self))
435 self
.AddUserStory(Page15(self
))
436 self
.AddUserStory(Page16(self
))
437 # Why: Test a requestAnimationFrame handler with concurrent CSS animation
438 self
.AddUserStory(ToughSchedulingCasesPage(
439 'file://tough_scheduling_cases/raf_animation.html',
441 # Why: Stress test for the scheduler
442 self
.AddUserStory(ToughSchedulingCasesPage(
443 'file://tough_scheduling_cases/raf_touch_animation.html',
445 self
.AddUserStory(Page17(self
))
446 self
.AddUserStory(Page18(self
))
447 self
.AddUserStory(Page19(self
))
448 self
.AddUserStory(Page20(self
))
449 # Why: Baseline for scrolling in the presence of a no-op touch handler
450 self
.AddUserStory(EmptyTouchHandlerPage(
456 # Why: Slow handler blocks scroll start
457 self
.AddUserStory(EmptyTouchHandlerPage(
463 # Why: Slow handler blocks scroll start until touch ACK timeout
464 self
.AddUserStory(EmptyTouchHandlerPage(
465 name
='desktop_slow_handler',
470 # Why: Scroll bounce showing repeated transitions between scrolling and
471 # sending synchronous touchmove events. Should be nearly as fast as
473 self
.AddUserStory(EmptyTouchHandlerPage(
479 # Why: Scroll bounce with slow handler, repeated blocking.
480 self
.AddUserStory(EmptyTouchHandlerPage(
481 name
='bounce_slow_handler',
486 # Why: Scroll bounce with slow handler on desktop, blocks only once until
488 self
.AddUserStory(EmptyTouchHandlerPage(
489 name
='bounce_desktop_slow_handler',
494 # Why: For measuring the latency of scroll-synchronized effects.
495 self
.AddUserStory(SynchronizedScrollOffsetPage(page_set
=self
))
496 # Why: Test loading a large amount of Javascript.
497 self
.AddUserStory(SecondBatchJsPage(page_set
=self
, variant
='light'))
498 self
.AddUserStory(SecondBatchJsPage(page_set
=self
, variant
='medium'))
499 self
.AddUserStory(SecondBatchJsPage(page_set
=self
, variant
='heavy'))