| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 import os | 4 import os |
| 5 | 5 |
| 6 from telemetry.core import util | 6 from telemetry.core import util |
| 7 | 7 |
| 8 class SmoothnessMetrics(object): | 8 class SmoothnessMetrics(object): |
| 9 def __init__(self, tab): | 9 def __init__(self, tab): |
| 10 self._tab = tab | 10 self._tab = tab |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 def end_values(self): | 45 def end_values(self): |
| 46 return self._tab.EvaluateJavaScript( | 46 return self._tab.EvaluateJavaScript( |
| 47 'window.__renderingStats.getEndValues()') | 47 'window.__renderingStats.getEndValues()') |
| 48 | 48 |
| 49 @property | 49 @property |
| 50 def deltas(self): | 50 def deltas(self): |
| 51 return self._tab.EvaluateJavaScript( | 51 return self._tab.EvaluateJavaScript( |
| 52 'window.__renderingStats.getDeltas()') | 52 'window.__renderingStats.getDeltas()') |
| 53 | 53 |
| 54 | 54 |
| 55 def DivideIfPossibleOrZero(numerator, denominator): | 55 def _DivideIfPossibleOrZero(numerator, denominator): |
| 56 if denominator == 0: | 56 if denominator == 0: |
| 57 return 0 | 57 return 0 |
| 58 return numerator / denominator | 58 return numerator / denominator |
| 59 | 59 |
| 60 def CalcScrollResults(rendering_stats_deltas, results): | |
| 61 num_frames_sent_to_screen = rendering_stats_deltas['numFramesSentToScreen'] | |
| 62 | 60 |
| 63 mean_frame_time_seconds = ( | 61 def _AddDeltaResult(deltas, results, stat_name, |
| 64 rendering_stats_deltas['totalTimeInSeconds'] / | 62 result_name, units, important=False): |
| 65 float(num_frames_sent_to_screen)) | 63 """Add a result from the given deltas object to the results. |
| 66 | 64 |
| 67 dropped_percent = ( | 65 Args: |
| 68 rendering_stats_deltas['droppedFrameCount'] / | 66 deltas: Deltas object returned by JS window.__renderingStats.getDeltas(). |
| 69 float(num_frames_sent_to_screen)) | 67 results: PageMeasurementResults object. |
| 68 stat_name: The attribute name of the statistic in the deltas object. |
| 69 result_name: The name of this statistic to give in the results. |
| 70 units: The units to give in the results. |
| 71 """ |
| 72 stat_value = deltas.get(stat_name, 0) |
| 73 data_type = 'default' if important else 'unimportant' |
| 74 results.Add(result_name, units, stat_value, data_type=data_type) |
| 70 | 75 |
| 71 num_impl_thread_scrolls = rendering_stats_deltas.get( | |
| 72 'numImplThreadScrolls', 0) | |
| 73 num_main_thread_scrolls = rendering_stats_deltas.get( | |
| 74 'numMainThreadScrolls', 0) | |
| 75 | 76 |
| 76 percent_impl_scrolled = DivideIfPossibleOrZero( | 77 def _AddAverageTimeResult(deltas, results, time_s_stat_name, count_stat_name, |
| 77 float(num_impl_thread_scrolls), | 78 result_name, important=False): |
| 78 num_impl_thread_scrolls + num_main_thread_scrolls) | 79 """Add a result which represents an average time. |
| 79 | 80 |
| 80 num_layers = ( | 81 Args: |
| 81 rendering_stats_deltas.get('numLayersDrawn', 0) / | 82 deltas: Deltas object returned by JS window.__renderingStats.getDeltas(). |
| 82 float(num_frames_sent_to_screen)) | 83 results: PageMeasurementResults object. |
| 84 time_s_stat_name: The name of a statistic which represents time in seconds |
| 85 count_stat_name: The name of a statistic which represents a total count |
| 86 result_name: The name of this statistic to give in the results. |
| 87 """ |
| 88 average_time_ms = _DivideIfPossibleOrZero( |
| 89 deltas.get(time_s_stat_name, 0) * 1000, |
| 90 deltas.get(count_stat_name, 0)) |
| 91 data_type = 'default' if important else 'unimportant' |
| 92 results.Add(result_name, 'ms', average_time_ms, data_type=data_type) |
| 83 | 93 |
| 84 num_missing_tiles = ( | |
| 85 rendering_stats_deltas.get('numMissingTiles', 0) / | |
| 86 float(num_frames_sent_to_screen)) | |
| 87 | 94 |
| 88 results.Add('mean_frame_time', 'ms', round(mean_frame_time_seconds * 1000, 3)) | 95 def CalcScrollResults(deltas, results): |
| 96 num_frames_sent_to_screen = deltas.get('numFramesSentToScreen', 0) |
| 97 |
| 98 total_time_s = deltas.get('totalTimeInSeconds', 0) |
| 99 mean_frame_time_ms = _DivideIfPossibleOrZero( |
| 100 float(total_time_s) * 1000, num_frames_sent_to_screen) |
| 101 results.Add('mean_frame_time', 'ms', round(mean_frame_time_ms, 3)) |
| 102 |
| 103 dropped_frame_count = deltas.get('droppedFrameCount', 0) |
| 104 dropped_percent = _DivideIfPossibleOrZero( |
| 105 float(dropped_frame_count), num_frames_sent_to_screen) |
| 89 results.Add('dropped_percent', '%', round(dropped_percent * 100, 1), | 106 results.Add('dropped_percent', '%', round(dropped_percent * 100, 1), |
| 90 data_type='unimportant') | 107 data_type='unimportant') |
| 108 |
| 109 num_impl_thread_scrolls = deltas.get('numImplThreadScrolls', 0) |
| 110 num_main_thread_scrolls = deltas.get('numMainThreadScrolls', 0) |
| 111 percent_impl_scrolled = _DivideIfPossibleOrZero( |
| 112 float(num_impl_thread_scrolls), |
| 113 num_impl_thread_scrolls + num_main_thread_scrolls) |
| 91 results.Add('percent_impl_scrolled', '%', | 114 results.Add('percent_impl_scrolled', '%', |
| 92 round(percent_impl_scrolled * 100, 1), | 115 round(percent_impl_scrolled * 100, 1), |
| 93 data_type='unimportant') | 116 data_type='unimportant') |
| 117 |
| 118 num_layers_drawn = deltas.get('numLayersDrawn', 0) |
| 119 num_layers = _DivideIfPossibleOrZero( |
| 120 float(num_layers_drawn), num_frames_sent_to_screen) |
| 94 results.Add('average_num_layers_drawn', '', round(num_layers, 1), | 121 results.Add('average_num_layers_drawn', '', round(num_layers, 1), |
| 95 data_type='unimportant') | 122 data_type='unimportant') |
| 123 |
| 124 num_missing_tiles = deltas.get('numMissingTiles', 0) |
| 125 num_missing_tiles = _DivideIfPossibleOrZero( |
| 126 float(num_missing_tiles), num_frames_sent_to_screen) |
| 96 results.Add('average_num_missing_tiles', '', round(num_missing_tiles, 1), | 127 results.Add('average_num_missing_tiles', '', round(num_missing_tiles, 1), |
| 97 data_type='unimportant') | 128 data_type='unimportant') |
| 98 | 129 |
| 99 def CalcTextureUploadResults(rendering_stats_deltas, results): | |
| 100 if (('totalCommitCount' not in rendering_stats_deltas) | |
| 101 or rendering_stats_deltas['totalCommitCount'] == 0) : | |
| 102 averageCommitTimeMs = 0 | |
| 103 else : | |
| 104 averageCommitTimeMs = ( | |
| 105 1000 * rendering_stats_deltas['totalCommitTimeInSeconds'] / | |
| 106 rendering_stats_deltas['totalCommitCount']) | |
| 107 | 130 |
| 108 results.Add('texture_upload_count', 'count', | 131 def CalcTextureUploadResults(deltas, results): |
| 109 rendering_stats_deltas.get('textureUploadCount', 0)) | 132 _AddDeltaResult(deltas, results, 'textureUploadCount', |
| 110 results.Add('total_texture_upload_time', 'seconds', | 133 'texture_upload_count', 'count') |
| 111 rendering_stats_deltas.get('totalTextureUploadTimeInSeconds', 0)) | 134 _AddDeltaResult(deltas, results, 'totalTextureUploadTimeInSeconds', |
| 112 results.Add('average_commit_time', 'ms', averageCommitTimeMs, | 135 'total_texture_upload_time', 'seconds') |
| 113 data_type='unimportant') | 136 _AddAverageTimeResult(deltas, results, 'totalCommitTimeInSeconds', |
| 137 'totalCommitCount', 'average_commit_time') |
| 138 |
| 114 | 139 |
| 115 def CalcFirstPaintTimeResults(results, tab): | 140 def CalcFirstPaintTimeResults(results, tab): |
| 116 if tab.browser.is_content_shell: | 141 if tab.browser.is_content_shell: |
| 117 results.Add('first_paint', 'ms', 'unsupported') | 142 results.Add('first_paint', 'ms', 'unsupported') |
| 118 return | 143 return |
| 119 | 144 |
| 120 tab.ExecuteJavaScript(""" | 145 tab.ExecuteJavaScript(""" |
| 121 window.__rafFired = false; | 146 window.__rafFired = false; |
| 122 window.webkitRequestAnimationFrame(function() { | 147 window.webkitRequestAnimationFrame(function() { |
| 123 window.__rafFired = true; | 148 window.__rafFired = true; |
| 124 }); | 149 }); """) |
| 125 """) | |
| 126 util.WaitFor(lambda: tab.EvaluateJavaScript('window.__rafFired'), 60) | 150 util.WaitFor(lambda: tab.EvaluateJavaScript('window.__rafFired'), 60) |
| 127 | 151 |
| 128 first_paint_secs = tab.EvaluateJavaScript( | 152 first_paint_secs = tab.EvaluateJavaScript( |
| 129 'window.chrome.loadTimes().firstPaintTime - ' + | 153 'window.chrome.loadTimes().firstPaintTime - ' + |
| 130 'window.chrome.loadTimes().startLoadTime') | 154 'window.chrome.loadTimes().startLoadTime') |
| 131 | 155 |
| 132 results.Add('first_paint', 'ms', round(first_paint_secs * 1000, 1)) | 156 results.Add('first_paint', 'ms', round(first_paint_secs * 1000, 1)) |
| 133 | 157 |
| 134 def CalcImageDecodingResults(rendering_stats_deltas, results): | |
| 135 totalDeferredImageDecodeCount = rendering_stats_deltas.get( | |
| 136 'totalDeferredImageDecodeCount', 0) | |
| 137 totalDeferredImageCacheHitCount = rendering_stats_deltas.get( | |
| 138 'totalDeferredImageCacheHitCount', 0) | |
| 139 totalImageGatheringCount = rendering_stats_deltas.get( | |
| 140 'totalImageGatheringCount', 0) | |
| 141 totalDeferredImageDecodeTimeInSeconds = rendering_stats_deltas.get( | |
| 142 'totalDeferredImageDecodeTimeInSeconds', 0) | |
| 143 totalImageGatheringTimeInSeconds = rendering_stats_deltas.get( | |
| 144 'totalImageGatheringTimeInSeconds', 0) | |
| 145 | 158 |
| 146 averageImageGatheringTime = DivideIfPossibleOrZero( | 159 def CalcImageDecodingResults(deltas, results): |
| 147 (totalImageGatheringTimeInSeconds * 1000), totalImageGatheringCount) | 160 _AddDeltaResult(deltas, results, 'totalDeferredImageDecodeCount', |
| 161 'total_deferred_image_decode_count', 'count') |
| 162 _AddDeltaResult(deltas, results, 'totalDeferredImageCacheHitCount', |
| 163 'total_image_cache_hit_count', 'count') |
| 164 _AddAverageTimeResult(deltas, results, 'totalImageGatheringTimeInSeconds', |
| 165 'totalImageGatheringCount', |
| 166 'average_image_gathering_time') |
| 167 _AddDeltaResult(deltas, results, 'totalDeferredImageDecodeTimeInSeconds', |
| 168 'total_deferred_image_decoding_time', 'seconds') |
| 148 | 169 |
| 149 results.Add('total_deferred_image_decode_count', 'count', | |
| 150 totalDeferredImageDecodeCount, | |
| 151 data_type='unimportant') | |
| 152 results.Add('total_image_cache_hit_count', 'count', | |
| 153 totalDeferredImageCacheHitCount, | |
| 154 data_type='unimportant') | |
| 155 results.Add('average_image_gathering_time', 'ms', averageImageGatheringTime, | |
| 156 data_type='unimportant') | |
| 157 results.Add('total_deferred_image_decoding_time', 'seconds', | |
| 158 totalDeferredImageDecodeTimeInSeconds, | |
| 159 data_type='unimportant') | |
| 160 | 170 |
| 161 def CalcAnalysisResults(rendering_stats_deltas, results): | 171 def CalcAnalysisResults(deltas, results): |
| 162 totalTilesAnalyzed = rendering_stats_deltas.get( | 172 _AddDeltaResult(deltas, results, 'totalTilesAnalayzed', |
| 163 'totalTilesAnalyzed', 0) | 173 'total_tiles_analyzed', 'count') |
| 164 solidColorTilesAnalyzed = rendering_stats_deltas.get( | 174 _AddDeltaResult(deltas, results, 'solidColorTilesAnalayzed', |
| 165 'solidColorTilesAnalyzed', 0) | 175 'solid_color_tiles_analyzed', 'count') |
| 166 totalTileAnalysisTimeInSeconds = rendering_stats_deltas.get( | 176 _AddAverageTimeResult(deltas, results, 'totalTileAnalysisTimeInSeconds', |
| 167 'totalTileAnalysisTimeInSeconds', 0) | 177 'totalTilesAnalyzed', 'average_tile_analysis_time') |
| 168 | 178 |
| 169 averageAnalysisTimeMS = \ | |
| 170 1000 * DivideIfPossibleOrZero(totalTileAnalysisTimeInSeconds, | |
| 171 totalTilesAnalyzed) | |
| 172 | 179 |
| 173 results.Add('total_tiles_analyzed', 'count', | 180 def CalcLatencyResults(deltas, results): |
| 174 totalTilesAnalyzed, | 181 _AddAverageTimeResult(deltas, results, 'totalInputLatency', |
| 175 data_type='unimportant') | 182 'inputEventCount', 'average_latency') |
| 176 results.Add('solid_color_tiles_analyzed', 'count', | 183 _AddAverageTimeResult(deltas, results, 'totalTouchUILatency', |
| 177 solidColorTilesAnalyzed, | 184 'touchUICount', 'average_touch_ui_latency') |
| 178 data_type='unimportant') | 185 _AddAverageTimeResult(deltas, results, 'totalTouchAckedLatency', |
| 179 results.Add('average_tile_analysis_time', 'ms', | 186 'touchAckedCount', 'average_touch_acked_latency') |
| 180 averageAnalysisTimeMS, | 187 _AddAverageTimeResult(deltas, results, 'totalScrollUpdateLatency', |
| 181 data_type='unimportant') | 188 'scrollUpdateCount', 'average_scroll_update_latency') |
| 182 | 189 |
| 183 def CalcLatency(rendering_stats_deltas, count_name, total_latency_name, | |
| 184 result_name, results): | |
| 185 eventCount = rendering_stats_deltas.get(count_name, 0) | |
| 186 totalLatencyInSeconds = rendering_stats_deltas.get(total_latency_name, 0) | |
| 187 averageLatency = DivideIfPossibleOrZero( | |
| 188 (totalLatencyInSeconds * 1000), eventCount) | |
| 189 results.Add(result_name, 'ms', averageLatency, data_type='unimportant') | |
| 190 | |
| 191 def CalcLatencyResults(rendering_stats_deltas, results): | |
| 192 CalcLatency(rendering_stats_deltas, 'inputEventCount', 'totalInputLatency', | |
| 193 'average_latency', results) | |
| 194 CalcLatency(rendering_stats_deltas, 'touchUICount', 'totalTouchUILatency', | |
| 195 'average_touch_ui_latency', results) | |
| 196 CalcLatency(rendering_stats_deltas, 'touchAckedCount', | |
| 197 'totalTouchAckedLatency', | |
| 198 'average_touch_acked_latency', | |
| 199 results) | |
| 200 CalcLatency(rendering_stats_deltas, 'scrollUpdateCount', | |
| 201 'totalScrollUpdateLatency', | |
| 202 'average_scroll_update_latency', results) | |
| OLD | NEW |