1 # Copyright (c) 2012 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.
8 from metrics import rendering_stats
9 from telemetry.page import page_measurement
10 from telemetry.page.perf_tests_helper import FlattenList
11 import telemetry.core.timeline.bounds as timeline_bounds
12 from telemetry.core.timeline.model import TimelineModel
13 from telemetry.core.timeline.model import MarkerMismatchError
14 from telemetry.core.timeline.model import MarkerOverlapError
16 TIMELINE_MARKER = 'RasterizeAndRecord'
19 class RasterizeAndRecord(page_measurement.PageMeasurement):
21 super(RasterizeAndRecord, self).__init__('', True)
23 self._compositing_features_enabled = False
26 def AddCommandLineArgs(cls, parser):
27 parser.add_option('--raster-record-repeat', type='int',
29 help='Repetitions in raster and record loops.'
30 'Higher values reduce variance, but can cause'
31 'instability (timeouts, event buffer overflows, etc.).')
32 parser.add_option('--start-wait-time', type='float',
34 help='Wait time before the benchmark is started '
35 '(must be long enought to load all content)')
36 parser.add_option('--stop-wait-time', type='float',
38 help='Wait time before measurement is taken '
39 '(must be long enough to render one frame)')
41 def CustomizeBrowserOptions(self, options):
42 # Run each raster task N times. This allows us to report the time for the
43 # best run, effectively excluding cache effects and time when the thread is
45 options.AppendExtraBrowserArgs([
46 '--enable-gpu-benchmarking',
47 '--slow-down-raster-scale-factor=%d' % options.raster_record_repeat,
48 # Enable impl-side-painting. Current version of benchmark only works for
50 '--enable-impl-side-painting',
51 '--force-compositing-mode',
52 '--enable-threaded-compositing'
55 def DidStartBrowser(self, browser):
56 # Check if the we actually have threaded forced compositing enabled.
57 system_info = browser.GetSystemInfo()
58 if (system_info.gpu.feature_status
59 and system_info.gpu.feature_status.get(
60 'compositing', None) == 'enabled_force_threaded'):
61 self._compositing_features_enabled = True
63 def MeasurePage(self, page, tab, results):
64 if not self._compositing_features_enabled:
65 logging.warning('Warning: compositing feature status unknown or not '+
66 'forced and threaded. Skipping measurement.')
69 # Rasterize only what's visible.
70 tab.ExecuteJavaScript(
71 'chrome.gpuBenchmarking.setRasterizeOnlyVisibleContent();')
73 # Wait until the page has loaded and come to a somewhat steady state.
74 # Needs to be adjusted for every device (~2 seconds for workstation).
75 time.sleep(self.options.start_wait_time)
77 # Render one frame before we start gathering a trace. On some pages, the
78 # first frame requested has more variance in the number of pixels
80 tab.ExecuteJavaScript(
81 'window.__rafFired = false;'
82 'window.webkitRequestAnimationFrame(function() {'
83 'chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers();'
84 'window.__rafFired = true;'
87 time.sleep(self.options.stop_wait_time)
88 tab.browser.StartTracing('webkit.console,benchmark', 60)
90 tab.ExecuteJavaScript(
91 'window.__rafFired = false;'
92 'window.webkitRequestAnimationFrame(function() {'
93 'chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers();'
94 'console.time("' + TIMELINE_MARKER + '");'
95 'window.__rafFired = true;'
97 # Wait until the frame was drawn.
98 # Needs to be adjusted for every device and for different
99 # raster_record_repeat counts.
100 # TODO(ernstm): replace by call-back.
101 time.sleep(self.options.stop_wait_time)
102 tab.ExecuteJavaScript(
103 'console.timeEnd("' + TIMELINE_MARKER + '")')
105 tracing_timeline_data = tab.browser.StopTracing()
106 timeline = TimelineModel(timeline_data=tracing_timeline_data)
108 timeline_markers = timeline.FindTimelineMarkers(TIMELINE_MARKER)
109 except (MarkerMismatchError, MarkerOverlapError) as e:
110 raise page_measurement.MeasurementFailure(str(e))
111 timeline_ranges = [ timeline_bounds.Bounds.CreateFromEvent(marker)
112 for marker in timeline_markers ]
113 renderer_process = timeline.GetRendererProcessFromTab(tab)
115 stats = rendering_stats.RenderingStats(
116 renderer_process, timeline.browser_process, timeline_ranges)
118 results.Add('rasterize_time', 'ms', max(FlattenList(stats.rasterize_times)))
119 results.Add('record_time', 'ms', max(FlattenList(stats.record_times)))
120 results.Add('rasterized_pixels', 'pixels',
121 max(FlattenList(stats.rasterized_pixel_counts)))
122 results.Add('recorded_pixels', 'pixels',
123 max(FlattenList(stats.recorded_pixel_counts)))
125 def CleanUpAfterPage(self, page, tab):
126 if tab.browser.is_tracing_running:
127 tab.browser.StopTracing()