OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 | 4 |
5 import Queue | 5 import Queue |
6 import datetime | 6 import datetime |
7 import logging | 7 import logging |
8 import re | 8 import re |
9 import threading | 9 import threading |
10 | 10 |
11 from pylib import perf_tests_helper | 11 from pylib import perf_tests_helper |
12 | 12 |
13 | 13 |
14 # Log marker containing SurfaceTexture timestamps. | 14 # Log marker containing SurfaceTexture timestamps. |
15 _SURFACE_TEXTURE_TIMESTAMPS_MESSAGE = 'SurfaceTexture update timestamps' | 15 _SURFACE_TEXTURE_TIMESTAMPS_MESSAGE = 'SurfaceTexture update timestamps' |
16 _SURFACE_TEXTURE_TIMESTAMP_RE = '\d+' | 16 _SURFACE_TEXTURE_TIMESTAMP_RE = '\d+' |
17 | 17 |
18 | 18 |
19 class SurfaceStatsCollector(object): | 19 class SurfaceStatsCollector(object): |
20 """Collects surface stats for a window from the output of SurfaceFlinger. | 20 """Collects surface stats for a SurfaceView from the output of SurfaceFlinger. |
21 | 21 |
22 Args: | 22 Args: |
23 adb: the adb coonection to use. | 23 adb: the adb connection to use. |
24 window_package: Package name of the window. | |
25 window_activity: Activity name of the window. | |
26 """ | 24 """ |
27 def __init__(self, adb, window_package, window_activity, trace_tag): | 25 def __init__(self, adb, trace_tag): |
28 self._adb = adb | 26 self._adb = adb |
29 self._window_package = window_package | |
30 self._window_activity = window_activity | |
31 self._trace_tag = trace_tag | 27 self._trace_tag = trace_tag |
32 self._collector_thread = None | 28 self._collector_thread = None |
33 self._use_legacy_method = False | 29 self._use_legacy_method = False |
34 self._surface_before = None | 30 self._surface_before = None |
35 self._get_data_event = None | 31 self._get_data_event = None |
36 self._data_queue = None | 32 self._data_queue = None |
37 self._stop_event = None | 33 self._stop_event = None |
38 | 34 |
39 def __enter__(self): | 35 def __enter__(self): |
40 assert not self._collector_thread | 36 assert not self._collector_thread |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 def _ClearSurfaceFlingerLatencyData(self): | 140 def _ClearSurfaceFlingerLatencyData(self): |
145 """Clears the SurfaceFlinger latency data. | 141 """Clears the SurfaceFlinger latency data. |
146 | 142 |
147 Returns: | 143 Returns: |
148 True if SurfaceFlinger latency is supported by the device, otherwise | 144 True if SurfaceFlinger latency is supported by the device, otherwise |
149 False. | 145 False. |
150 """ | 146 """ |
151 # The command returns nothing if it is supported, otherwise returns many | 147 # The command returns nothing if it is supported, otherwise returns many |
152 # lines of result just like 'dumpsys SurfaceFlinger'. | 148 # lines of result just like 'dumpsys SurfaceFlinger'. |
153 results = self._adb.RunShellCommand( | 149 results = self._adb.RunShellCommand( |
154 'dumpsys SurfaceFlinger --latency-clear %s/%s' % | 150 'dumpsys SurfaceFlinger --latency-clear SurfaceView') |
155 (self._window_package, self._window_activity)) | |
156 return not len(results) | 151 return not len(results) |
157 | 152 |
158 def _GetSurfaceFlingerLatencyData(self, previous_timestamp, latencies): | 153 def _GetSurfaceFlingerLatencyData(self, previous_timestamp, latencies): |
159 """Returns collected SurfaceFlinger latency data. | 154 """Returns collected SurfaceFlinger latency data. |
160 | 155 |
161 Args: | 156 Args: |
162 previous_timestamp: The timestamp returned from the previous call or 0. | 157 previous_timestamp: The timestamp returned from the previous call or 0. |
163 Only data after this timestamp will be returned. | 158 Only data after this timestamp will be returned. |
164 latencies: A list to receive latency data. The latencies are integers | 159 latencies: A list to receive latency data. The latencies are integers |
165 each of which is the number of refresh periods of each frame. | 160 each of which is the number of refresh periods of each frame. |
(...skipping 23 matching lines...) Expand all Loading... |
189 # | 184 # |
190 # The difference between the 1st and 3rd timestamp is the frame-latency. | 185 # The difference between the 1st and 3rd timestamp is the frame-latency. |
191 # An interesting data is when the frame latency crosses a refresh period | 186 # An interesting data is when the frame latency crosses a refresh period |
192 # boundary, this can be calculated this way: | 187 # boundary, this can be calculated this way: |
193 # | 188 # |
194 # ceil((C - A) / refresh-period) | 189 # ceil((C - A) / refresh-period) |
195 # | 190 # |
196 # (each time the number above changes, we have a "jank"). | 191 # (each time the number above changes, we have a "jank"). |
197 # If this happens a lot during an animation, the animation appears | 192 # If this happens a lot during an animation, the animation appears |
198 # janky, even if it runs at 60 fps in average. | 193 # janky, even if it runs at 60 fps in average. |
| 194 # |
| 195 # We use the special "SurfaceView" window name because the statistics for |
| 196 # the activity's main window are not updated when the main web content is |
| 197 # composited into a SurfaceView. |
199 results = self._adb.RunShellCommand( | 198 results = self._adb.RunShellCommand( |
200 'dumpsys SurfaceFlinger --latency %s/%s' % | 199 'dumpsys SurfaceFlinger --latency SurfaceView', log_result=True) |
201 (self._window_package, self._window_activity), log_result=True) | |
202 if not len(results): | 200 if not len(results): |
203 return (None, None) | 201 return (None, None) |
204 | 202 |
205 refresh_period = int(results[0]) | 203 refresh_period = int(results[0]) |
206 last_timestamp = previous_timestamp | 204 last_timestamp = previous_timestamp |
207 first_timestamp = 0 | 205 first_timestamp = 0 |
208 for line in results[1:]: | 206 for line in results[1:]: |
209 fields = line.split() | 207 fields = line.split() |
210 if len(fields) == 3: | 208 if len(fields) == 3: |
211 timestamp = long(fields[0]) | 209 timestamp = long(fields[0]) |
(...skipping 24 matching lines...) Expand all Loading... |
236 try: | 234 try: |
237 cur_surface = int(match.group(1), 16) | 235 cur_surface = int(match.group(1), 16) |
238 except Exception: | 236 except Exception: |
239 logging.error('Failed to parse current surface from ' + match.group(1)) | 237 logging.error('Failed to parse current surface from ' + match.group(1)) |
240 else: | 238 else: |
241 logging.warning('Failed to call SurfaceFlinger surface ' + results[0]) | 239 logging.warning('Failed to call SurfaceFlinger surface ' + results[0]) |
242 return { | 240 return { |
243 'page_flip_count': cur_surface, | 241 'page_flip_count': cur_surface, |
244 'timestamp': datetime.datetime.now(), | 242 'timestamp': datetime.datetime.now(), |
245 } | 243 } |
OLD | NEW |