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 | 4 |
5 from operator import attrgetter | 5 from operator import attrgetter |
| 6 from telemetry.page import page_measurement |
6 | 7 |
7 # These are LatencyInfo component names indicating the various components | 8 # These are LatencyInfo component names indicating the various components |
8 # that the input event has travelled through. | 9 # that the input event has travelled through. |
9 # This is when the input event first reaches chrome. | 10 # This is when the input event first reaches chrome. |
10 UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT' | 11 UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT' |
11 # This is when the input event was originally created by OS. | 12 # This is when the input event was originally created by OS. |
12 ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT' | 13 ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT' |
13 # This is when the input event was sent from browser to renderer. | 14 # This is when the input event was sent from browser to renderer. |
14 BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT' | 15 BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT' |
15 # This is when the input event has reached swap buffer. | 16 # This is when the input event has reached swap buffer. |
16 END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT' | 17 END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT' |
17 | 18 |
18 | 19 |
| 20 class NotEnoughFramesError(page_measurement.MeasurementFailure): |
| 21 def __init__(self, frame_count): |
| 22 super(NotEnoughFramesError, self).__init__( |
| 23 'Only %i frame timestamps were collected ' % frame_count + |
| 24 '(at least two are required).\n' |
| 25 'Issues that have caused this in the past:\n' + |
| 26 '- Browser bugs that prevents the page from redrawing\n' + |
| 27 '- Bugs in the synthetic gesture code\n' + |
| 28 '- Page and benchmark out of sync (e.g. clicked element was renamed)\n' + |
| 29 '- Pages that render extremely slow\n' + |
| 30 '- Pages that can\'t be scrolled') |
| 31 |
| 32 |
19 def GetScrollInputLatencyEvents(scroll_type, browser_process, timeline_range): | 33 def GetScrollInputLatencyEvents(scroll_type, browser_process, timeline_range): |
20 """Get scroll events' LatencyInfo from the browser process's trace buffer | 34 """Get scroll events' LatencyInfo from the browser process's trace buffer |
21 that are within the timeline_range. | 35 that are within the timeline_range. |
22 | 36 |
23 Scroll events (MouseWheel, GestureScrollUpdate or JS scroll on TouchMove) | 37 Scroll events (MouseWheel, GestureScrollUpdate or JS scroll on TouchMove) |
24 dump their LatencyInfo into trace buffer as async trace event with name | 38 dump their LatencyInfo into trace buffer as async trace event with name |
25 "InputLatency". The trace event has a memeber 'step' containing its event | 39 "InputLatency". The trace event has a memeber 'step' containing its event |
26 type and a memeber 'data' containing its latency history. | 40 type and a memeber 'data' containing its latency history. |
27 | 41 |
28 """ | 42 """ |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 self.mouse_wheel_scroll_latency.append([]) | 167 self.mouse_wheel_scroll_latency.append([]) |
154 self.touch_scroll_latency.append([]) | 168 self.touch_scroll_latency.append([]) |
155 self.js_touch_scroll_latency.append([]) | 169 self.js_touch_scroll_latency.append([]) |
156 | 170 |
157 if timeline_range.is_empty: | 171 if timeline_range.is_empty: |
158 continue | 172 continue |
159 self.initMainThreadStatsFromTimeline(timeline_range) | 173 self.initMainThreadStatsFromTimeline(timeline_range) |
160 self.initImplThreadStatsFromTimeline(timeline_range) | 174 self.initImplThreadStatsFromTimeline(timeline_range) |
161 self.initScrollLatencyStatsFromTimeline(browser_process, timeline_range) | 175 self.initScrollLatencyStatsFromTimeline(browser_process, timeline_range) |
162 | 176 |
| 177 # Check if we have collected at least 2 frames in every range. Otherwise we |
| 178 # can't compute any meaningful metrics. |
| 179 for segment in self.frame_timestamps: |
| 180 if len(segment) < 2: |
| 181 raise NotEnoughFramesError(len(segment)) |
| 182 |
163 def initScrollLatencyStatsFromTimeline(self, browser_process, timeline_range): | 183 def initScrollLatencyStatsFromTimeline(self, browser_process, timeline_range): |
164 mouse_wheel_events = GetScrollInputLatencyEvents( | 184 mouse_wheel_events = GetScrollInputLatencyEvents( |
165 "MouseWheel", browser_process, timeline_range) | 185 "MouseWheel", browser_process, timeline_range) |
166 self.mouse_wheel_scroll_latency = ComputeMouseWheelScrollLatency( | 186 self.mouse_wheel_scroll_latency = ComputeMouseWheelScrollLatency( |
167 mouse_wheel_events) | 187 mouse_wheel_events) |
168 | 188 |
169 touch_scroll_events = GetScrollInputLatencyEvents( | 189 touch_scroll_events = GetScrollInputLatencyEvents( |
170 "GestureScrollUpdate", browser_process, timeline_range) | 190 "GestureScrollUpdate", browser_process, timeline_range) |
171 self.touch_scroll_latency = ComputeTouchScrollLatency(touch_scroll_events) | 191 self.touch_scroll_latency = ComputeTouchScrollLatency(touch_scroll_events) |
172 | 192 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 self.frame_timestamps[-1].append( | 245 self.frame_timestamps[-1].append( |
226 event.start) | 246 event.start) |
227 if not first_frame: | 247 if not first_frame: |
228 self.frame_times[-1].append(round(self.frame_timestamps[-1][-1] - | 248 self.frame_times[-1].append(round(self.frame_timestamps[-1][-1] - |
229 self.frame_timestamps[-1][-2], 2)) | 249 self.frame_timestamps[-1][-2], 2)) |
230 first_frame = False | 250 first_frame = False |
231 self.rasterize_times[-1].append(1000.0 * | 251 self.rasterize_times[-1].append(1000.0 * |
232 event.args['data']['rasterize_time']) | 252 event.args['data']['rasterize_time']) |
233 self.rasterized_pixel_counts[-1].append( | 253 self.rasterized_pixel_counts[-1].append( |
234 event.args['data']['rasterized_pixel_count']) | 254 event.args['data']['rasterized_pixel_count']) |
OLD | NEW |