1 # Copyright 2013 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 import os 5 6 from telemetry.core import util 7 8 class SmoothnessMetrics(object): 9 def __init__(self, tab): 10 self._tab = tab 11 with open( 12 os.path.join(os.path.dirname(__file__), 13 'smoothness.js')) as f: 14 js = f.read() 15 tab.ExecuteJavaScript(js) 16 17 def Start(self): 18 self._tab.ExecuteJavaScript( 19 'window.__renderingStats = new __RenderingStats();' 20 'window.__renderingStats.start()') 21 22 def SetNeedsDisplayOnAllLayersAndStart(self): 23 self._tab.ExecuteJavaScript( 24 'chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers();' 25 'window.__renderingStats = new __RenderingStats();' 26 'window.__renderingStats.start()') 27 28 def Stop(self): 29 self._tab.ExecuteJavaScript('window.__renderingStats.stop()') 30 31 def BindToAction(self, action): 32 # Make the scroll test start and stop measurement automatically. 33 self._tab.ExecuteJavaScript( 34 'window.__renderingStats = new __RenderingStats();') 35 action.BindMeasurementJavaScript(self._tab, 36 'window.__renderingStats.start();', 37 'window.__renderingStats.stop();') 38 39 @property 40 def start_values(self): 41 return self._tab.EvaluateJavaScript( 42 'window.__renderingStats.getStartValues()') 43 44 @property 45 def end_values(self): 46 return self._tab.EvaluateJavaScript( 47 'window.__renderingStats.getEndValues()') 48 49 @property 50 def deltas(self): 51 return self._tab.EvaluateJavaScript( 52 'window.__renderingStats.getDeltas()') 53 54 def Average(numerator, denominator, scale = None, precision = None): 55 if denominator == 0: 56 return 0 57 avg = float(numerator) / float(denominator) 58 if scale: 59 avg *= scale 60 if precision: 61 avg = round(avg, precision) 62 return avg 63 64 def CalcFirstPaintTimeResults(results, tab): 65 if tab.browser.is_content_shell: 66 results.Add('first_paint', 'ms', 'unsupported') 67 return 68 69 tab.ExecuteJavaScript(""" 70 window.__rafFired = false; 71 window.webkitRequestAnimationFrame(function() { 72 window.__rafFired = true; 73 }); 74 """) 75 util.WaitFor(lambda: tab.EvaluateJavaScript('window.__rafFired'), 60) 76 77 first_paint_secs = tab.EvaluateJavaScript( 78 'window.chrome.loadTimes().firstPaintTime - ' + 79 'window.chrome.loadTimes().startLoadTime') 80 81 results.Add('first_paint', 'ms', round(first_paint_secs * 1000, 1)) 82 83 def CalcResults(benchmark_stats, results): 84 s = benchmark_stats 85 86 # Scroll Results 87 results.Add('mean_frame_time', 'ms', 88 Average(s.total_time, s.screen_frame_count, 1000, 3)) 89 results.Add('dropped_percent', '%', 90 Average(s.dropped_frame_count, s.screen_frame_count, 91 100, 1), 92 data_type='unimportant') 93 results.Add('percent_impl_scrolled', '%', 94 Average(s.impl_thread_scroll_count, 95 s.impl_thread_scroll_count + 96 s.main_thread_scroll_count, 97 100, 1), 98 data_type='unimportant') 99 results.Add('average_num_layers_drawn', '', 100 Average(s.drawn_layers_count, s.screen_frame_count, 1, 1), 101 data_type='unimportant') 102 results.Add('average_num_missing_tiles', '', 103 Average(s.missing_tile_count, s.screen_frame_count, 1, 1), 104 data_type='unimportant') 105 106 # Texture Upload Results 107 results.Add('average_commit_time', 'ms', 108 Average(s.commit_time, s.commit_count, 1000, 3), 109 data_type='unimportant') 110 results.Add('texture_upload_count', 'count', 111 s.texture_upload_count) 112 results.Add('total_texture_upload_time', 'seconds', 113 s.texture_upload_time) 114 115 # Image Decoding Results 116 results.Add('total_deferred_image_decode_count', 'count', 117 s.deferred_image_decode_count, 118 data_type='unimportant') 119 results.Add('total_image_cache_hit_count', 'count', 120 s.deferred_image_cache_hits, 121 data_type='unimportant') 122 results.Add('average_image_gathering_time', 'ms', 123 Average(s.image_gathering_time, s.image_gathering_count, 124 1000, 3), 125 data_type='unimportant') 126 results.Add('total_deferred_image_decoding_time', 'seconds', 127 s.deferred_image_decode_time, 128 data_type='unimportant') 129 130 # Tile Analysis Results 131 results.Add('total_tiles_analyzed', 'count', 132 s.tile_analysis_count, 133 data_type='unimportant') 134 results.Add('solid_color_tiles_analyzed', 'count', 135 s.solid_color_tile_analysis_count, 136 data_type='unimportant') 137 results.Add('average_tile_analysis_time', 'ms', 138 Average(s.tile_analysis_time, s.tile_analysis_count, 139 1000, 3), 140 data_type='unimportant') 141 142 # Latency Results 143 results.Add('average_latency', 'ms', 144 Average(s.input_event_latency, s.input_event_count, 145 1000, 3), 146 data_type='unimportant') 147 results.Add('average_touch_ui_latency', 'ms', 148 Average(s.touch_ui_latency, s.touch_ui_count, 1000, 3), 149 data_type='unimportant') 150 results.Add('average_touch_acked_latency', 'ms', 151 Average(s.touch_acked_latency, s.touch_acked_count, 152 1000, 3), 153 data_type='unimportant') 154 results.Add('average_scroll_update_latency', 'ms', 155 Average(s.scroll_update_latency, s.scroll_update_count, 156 1000, 3), 157 data_type='unimportant') 158