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.
4 from perf_tools
import smoothness_measurement
5 from telemetry
.core
import util
6 from telemetry
.page
import page_benchmark
8 class DidNotScrollException(page_benchmark
.MeasurementFailure
):
10 super(DidNotScrollException
, self
).__init
__('Page did not scroll')
12 def DivideIfPossibleOrZero(numerator
, denominator
):
15 return numerator
/ denominator
17 def CalcScrollResults(rendering_stats_deltas
, results
):
18 num_frames_sent_to_screen
= rendering_stats_deltas
['numFramesSentToScreen']
20 mean_frame_time_seconds
= (
21 rendering_stats_deltas
['totalTimeInSeconds'] /
22 float(num_frames_sent_to_screen
))
25 rendering_stats_deltas
['droppedFrameCount'] /
26 float(num_frames_sent_to_screen
))
28 num_impl_thread_scrolls
= rendering_stats_deltas
.get(
29 'numImplThreadScrolls', 0)
30 num_main_thread_scrolls
= rendering_stats_deltas
.get(
31 'numMainThreadScrolls', 0)
33 percent_impl_scrolled
= DivideIfPossibleOrZero(
34 float(num_impl_thread_scrolls
),
35 num_impl_thread_scrolls
+ num_main_thread_scrolls
)
38 rendering_stats_deltas
.get('numLayersDrawn', 0) /
39 float(num_frames_sent_to_screen
))
42 rendering_stats_deltas
.get('numMissingTiles', 0) /
43 float(num_frames_sent_to_screen
))
45 results
.Add('mean_frame_time', 'ms', round(mean_frame_time_seconds
* 1000, 3))
46 results
.Add('dropped_percent', '%', round(dropped_percent
* 100, 1),
47 data_type
='unimportant')
48 results
.Add('percent_impl_scrolled', '%',
49 round(percent_impl_scrolled
* 100, 1),
50 data_type
='unimportant')
51 results
.Add('average_num_layers_drawn', '', round(num_layers
, 1),
52 data_type
='unimportant')
53 results
.Add('average_num_missing_tiles', '', round(num_missing_tiles
, 1),
54 data_type
='unimportant')
56 def CalcPaintingResults(rendering_stats_deltas
, results
):
57 totalPaintTime
= rendering_stats_deltas
.get('totalPaintTimeInSeconds', 0)
58 totalRasterizeTime
= rendering_stats_deltas
.get(
59 'totalRasterizeTimeInSeconds', 0)
60 totalPixelsPainted
= rendering_stats_deltas
.get('totalPixelsPainted', 0)
61 totalPixelsRasterized
= rendering_stats_deltas
.get('totalPixelsRasterized', 0)
63 megapixelsPaintedPerSecond
= DivideIfPossibleOrZero(
64 (totalPixelsPainted
/ 1000000.0), totalPaintTime
)
66 megapixelsRasterizedPerSecond
= DivideIfPossibleOrZero(
67 (totalPixelsRasterized
/ 1000000.0), totalRasterizeTime
)
69 results
.Add('total_paint_time', 'seconds', totalPaintTime
)
70 results
.Add('total_rasterize_time', 'seconds', totalRasterizeTime
,
71 data_type
='unimportant')
72 results
.Add('total_pixels_painted', '', totalPixelsPainted
,
73 data_type
='unimportant')
74 results
.Add('total_pixels_rasterized', '', totalPixelsRasterized
,
75 data_type
='unimportant')
76 results
.Add('megapixels_painted_per_second', '', megapixelsPaintedPerSecond
,
77 data_type
='unimportant')
78 results
.Add('megapixels_rasterized_per_second', '',
79 megapixelsRasterizedPerSecond
, data_type
='unimportant')
80 results
.Add('total_paint_and_rasterize_time', 'seconds', totalPaintTime
+
81 totalRasterizeTime
, data_type
='unimportant')
83 def CalcTextureUploadResults(rendering_stats_deltas
, results
):
84 if (('totalCommitCount' not in rendering_stats_deltas
)
85 or rendering_stats_deltas
['totalCommitCount'] == 0) :
86 averageCommitTimeMs
= 0
88 averageCommitTimeMs
= (
89 1000 * rendering_stats_deltas
['totalCommitTimeInSeconds'] /
90 rendering_stats_deltas
['totalCommitCount'])
92 results
.Add('texture_upload_count', 'count',
93 rendering_stats_deltas
.get('textureUploadCount', 0))
94 results
.Add('total_texture_upload_time', 'seconds',
95 rendering_stats_deltas
.get('totalTextureUploadTimeInSeconds', 0))
96 results
.Add('average_commit_time', 'ms', averageCommitTimeMs
,
97 data_type
='unimportant')
99 def CalcFirstPaintTimeResults(results
, tab
):
100 if tab
.browser
.is_content_shell
:
101 results
.Add('first_paint', 'ms', 'unsupported')
104 tab
.ExecuteJavaScript("""
105 window.__rafFired = false;
106 window.webkitRequestAnimationFrame(function() {
107 window.__rafFired = true;
110 util
.WaitFor(lambda: tab
.EvaluateJavaScript('window.__rafFired'), 60)
112 first_paint_secs
= tab
.EvaluateJavaScript(
113 'window.chrome.loadTimes().firstPaintTime - ' +
114 'window.chrome.loadTimes().startLoadTime')
116 results
.Add('first_paint', 'ms', round(first_paint_secs
* 1000, 1))
118 def CalcImageDecodingResults(rendering_stats_deltas
, results
):
119 totalDeferredImageDecodeCount
= rendering_stats_deltas
.get(
120 'totalDeferredImageDecodeCount', 0)
121 totalDeferredImageCacheHitCount
= rendering_stats_deltas
.get(
122 'totalDeferredImageCacheHitCount', 0)
123 totalImageGatheringCount
= rendering_stats_deltas
.get(
124 'totalImageGatheringCount', 0)
125 totalDeferredImageDecodeTimeInSeconds
= rendering_stats_deltas
.get(
126 'totalDeferredImageDecodeTimeInSeconds', 0)
127 totalImageGatheringTimeInSeconds
= rendering_stats_deltas
.get(
128 'totalImageGatheringTimeInSeconds', 0)
130 averageImageGatheringTime
= DivideIfPossibleOrZero(
131 (totalImageGatheringTimeInSeconds
* 1000), totalImageGatheringCount
)
133 results
.Add('total_deferred_image_decode_count', 'count',
134 totalDeferredImageDecodeCount
,
135 data_type
='unimportant')
136 results
.Add('total_image_cache_hit_count', 'count',
137 totalDeferredImageCacheHitCount
,
138 data_type
='unimportant')
139 results
.Add('average_image_gathering_time', 'ms', averageImageGatheringTime
,
140 data_type
='unimportant')
141 results
.Add('total_deferred_image_decoding_time', 'seconds',
142 totalDeferredImageDecodeTimeInSeconds
,
143 data_type
='unimportant')
145 class SmoothnessBenchmark(page_benchmark
.PageBenchmark
):
147 super(SmoothnessBenchmark
, self
).__init
__('smoothness')
148 self
.force_enable_threaded_compositing
= False
149 self
.use_gpu_benchmarking_extension
= True
150 self
._measurement
= None
152 def AddCommandLineOptions(self
, parser
):
153 parser
.add_option('--report-all-results', dest
='report_all_results',
155 help='Reports all data collected, not just FPS')
157 def CustomizeBrowserOptions(self
, options
):
158 if self
.use_gpu_benchmarking_extension
:
159 options
.extra_browser_args
.append('--enable-gpu-benchmarking')
160 if self
.force_enable_threaded_compositing
:
161 options
.extra_browser_args
.append('--enable-threaded-compositing')
163 def CanRunForPage(self
, page
):
164 return hasattr(page
, 'smoothness')
166 def WillRunAction(self
, page
, tab
, action
):
167 if tab
.browser
.platform
.IsRawDisplayFrameRateSupported():
168 tab
.browser
.platform
.StartRawDisplayFrameRateMeasurement()
169 self
._measurement
= smoothness_measurement
.SmoothnessMeasurement(tab
)
170 if action
.CanBeBound():
171 self
._measurement
.BindToAction(action
)
173 self
._measurement
.Start()
175 def DidRunAction(self
, page
, tab
, action
):
176 if tab
.browser
.platform
.IsRawDisplayFrameRateSupported():
177 tab
.browser
.platform
.StopRawDisplayFrameRateMeasurement()
178 if not action
.CanBeBound():
179 self
._measurement
.Stop()
181 def MeasurePage(self
, page
, tab
, results
):
182 rendering_stats_deltas
= self
._measurement
.deltas
184 if not (rendering_stats_deltas
['numFramesSentToScreen'] > 0):
185 raise DidNotScrollException()
187 load_timings
= tab
.EvaluateJavaScript("window.performance.timing")
188 load_time_seconds
= (
189 float(load_timings
['loadEventStart']) -
190 load_timings
['navigationStart']) / 1000
191 dom_content_loaded_time_seconds
= (
192 float(load_timings
['domContentLoadedEventStart']) -
193 load_timings
['navigationStart']) / 1000
194 results
.Add('load_time', 'seconds', load_time_seconds
)
195 results
.Add('dom_content_loaded_time', 'seconds',
196 dom_content_loaded_time_seconds
)
198 CalcFirstPaintTimeResults(results
, tab
)
199 CalcScrollResults(rendering_stats_deltas
, results
)
200 CalcPaintingResults(rendering_stats_deltas
, results
)
201 CalcTextureUploadResults(rendering_stats_deltas
, results
)
202 CalcImageDecodingResults(rendering_stats_deltas
, results
)
204 if self
.options
.report_all_results
:
205 for k
, v
in rendering_stats_deltas
.iteritems():
206 results
.Add(k
, '', v
)
208 if tab
.browser
.platform
.IsRawDisplayFrameRateSupported():
209 for r
in tab
.browser
.platform
.GetRawDisplayFrameRateMeasurements():
210 results
.Add(r
.name
, r
.unit
, r
.value
)