Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: tools/perf/metrics/rendering_stats.py

Issue 187343004: Revert of re-land: Use browser compositor rendering stats in smoothness (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/perf/metrics/rendering_stats_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 6
7 # These are LatencyInfo component names indicating the various components 7 # These are LatencyInfo component names indicating the various components
8 # that the input event has travelled through. 8 # that the input event has travelled through.
9 # This is when the input event first reaches chrome. 9 # This is when the input event first reaches chrome.
10 UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT' 10 UI_COMP_NAME = 'INPUT_EVENT_LATENCY_UI_COMPONENT'
11 # This is when the input event was originally created by OS. 11 # This is when the input event was originally created by OS.
12 ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT' 12 ORIGINAL_COMP_NAME = 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT'
13 # This is when the input event was sent from browser to renderer. 13 # This is when the input event was sent from browser to renderer.
14 BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT' 14 BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT'
15 # This is when the input event has reached swap buffer. 15 # This is when the input event has reached swap buffer.
16 END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT' 16 END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT'
17 17
18
19 def GetScrollInputLatencyEvents(scroll_type, browser_process, timeline_range): 18 def GetScrollInputLatencyEvents(scroll_type, browser_process, timeline_range):
20 """Get scroll events' LatencyInfo from the browser process's trace buffer 19 """Get scroll events' LatencyInfo from the browser process's trace buffer
21 that are within the timeline_range. 20 that are within the timeline_range.
22 21
23 Scroll events (MouseWheel, GestureScrollUpdate or JS scroll on TouchMove) 22 Scroll events (MouseWheel, GestureScrollUpdate or JS scroll on TouchMove)
24 dump their LatencyInfo into trace buffer as async trace event with name 23 dump their LatencyInfo into trace buffer as async trace event with name
25 "InputLatency". The trace event has a memeber 'step' containing its event 24 "InputLatency". The trace event has a memeber 'step' containing its event
26 type and a memeber 'data' containing its latency history. 25 type and a memeber 'data' containing its latency history.
27 26
28 """ 27 """
29 scroll_events = [] 28 scroll_events = []
30 if not browser_process: 29 if not browser_process:
31 return scroll_events 30 return scroll_events
32 for event in browser_process.IterAllAsyncSlicesOfName("InputLatency"): 31 for event in browser_process.IterAllAsyncSlicesOfName("InputLatency"):
33 if event.start >= timeline_range.min and event.end <= timeline_range.max: 32 if event.start >= timeline_range.min and event.end <= timeline_range.max:
34 for ss in event.sub_slices: 33 for ss in event.sub_slices:
35 if 'step' not in ss.args: 34 if 'step' not in ss.args:
36 continue 35 continue
37 if 'data' not in ss.args: 36 if 'data' not in ss.args:
38 continue 37 continue
39 if ss.args['step'] == scroll_type: 38 if ss.args['step'] == scroll_type:
40 scroll_events.append(ss) 39 scroll_events.append(ss)
41 return scroll_events 40 return scroll_events
42 41
43
44 def ComputeMouseWheelScrollLatency(mouse_wheel_events): 42 def ComputeMouseWheelScrollLatency(mouse_wheel_events):
45 """ Compute the mouse wheel scroll latency. 43 """ Compute the mouse wheel scroll latency.
46 44
47 Mouse wheel scroll latency is the time from when mouse wheel event is sent 45 Mouse wheel scroll latency is the time from when mouse wheel event is sent
48 from browser RWH to renderer (the timestamp of component 46 from browser RWH to renderer (the timestamp of component
49 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT') to when the scrolled page is 47 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT') to when the scrolled page is
50 buffer swapped (the timestamp of component 48 buffer swapped (the timestamp of component
51 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT') 49 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT')
52 50
53 """ 51 """
54 mouse_wheel_latency = [] 52 mouse_wheel_latency = []
55 for event in mouse_wheel_events: 53 for event in mouse_wheel_events:
56 data = event.args['data'] 54 data = event.args['data']
57 if BEGIN_COMP_NAME in data and END_COMP_NAME in data: 55 if BEGIN_COMP_NAME in data and END_COMP_NAME in data:
58 latency = data[END_COMP_NAME]['time'] - data[BEGIN_COMP_NAME]['time'] 56 latency = data[END_COMP_NAME]['time'] - data[BEGIN_COMP_NAME]['time']
59 mouse_wheel_latency.append(latency / 1000.0) 57 mouse_wheel_latency.append(latency / 1000.0)
60 return mouse_wheel_latency 58 return mouse_wheel_latency
61 59
62
63 def ComputeTouchScrollLatency(touch_scroll_events): 60 def ComputeTouchScrollLatency(touch_scroll_events):
64 """ Compute the touch scroll latency. 61 """ Compute the touch scroll latency.
65 62
66 Touch scroll latency is the time from when the touch event is created to 63 Touch scroll latency is the time from when the touch event is created to
67 when the scrolled page is buffer swapped. 64 when the scrolled page is buffer swapped.
68 Touch event on differnt platforms uses different LatencyInfo component to 65 Touch event on differnt platforms uses different LatencyInfo component to
69 record its creation timestamp. On Aura, the creation time is kept in 66 record its creation timestamp. On Aura, the creation time is kept in
70 'INPUT_EVENT_LATENCY_UI_COMPONENT' . On Android, the creation time is kept 67 'INPUT_EVENT_LATENCY_UI_COMPONENT' . On Android, the creation time is kept
71 in 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT'. 68 in 'INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT'.
72 69
73 """ 70 """
74 touch_scroll_latency = [] 71 touch_scroll_latency = []
75 for event in touch_scroll_events: 72 for event in touch_scroll_events:
76 data = event.args['data'] 73 data = event.args['data']
77 if END_COMP_NAME in data: 74 if END_COMP_NAME in data:
78 end_time = data[END_COMP_NAME]['time'] 75 end_time = data[END_COMP_NAME]['time']
79 if UI_COMP_NAME in data and ORIGINAL_COMP_NAME in data: 76 if UI_COMP_NAME in data and ORIGINAL_COMP_NAME in data:
80 raise ValueError, 'LatencyInfo has both UI and ORIGINAL component' 77 raise ValueError, 'LatencyInfo has both UI and ORIGINAL component'
81 if UI_COMP_NAME in data: 78 if UI_COMP_NAME in data:
82 latency = end_time - data[UI_COMP_NAME]['time'] 79 latency = end_time - data[UI_COMP_NAME]['time']
83 touch_scroll_latency.append(latency / 1000.0) 80 touch_scroll_latency.append(latency / 1000.0)
84 elif ORIGINAL_COMP_NAME in data: 81 elif ORIGINAL_COMP_NAME in data:
85 latency = end_time - data[ORIGINAL_COMP_NAME]['time'] 82 latency = end_time - data[ORIGINAL_COMP_NAME]['time']
86 touch_scroll_latency.append(latency / 1000.0) 83 touch_scroll_latency.append(latency / 1000.0)
87 return touch_scroll_latency 84 return touch_scroll_latency
88 85
89
90 def HasRenderingStats(process):
91 """ Returns True if the process contains at least one
92 BenchmarkInstrumentation::*RenderingStats event with a frame.
93 """
94 for event in process.IterAllSlicesOfName(
95 'BenchmarkInstrumentation::MainThreadRenderingStats'):
96 if 'data' in event.args and event.args['data']['frame_count'] == 1:
97 return True
98 for event in process.IterAllSlicesOfName(
99 'BenchmarkInstrumentation::ImplThreadRenderingStats'):
100 if 'data' in event.args and event.args['data']['frame_count'] == 1:
101 return True
102 return False
103
104
105 class RenderingStats(object): 86 class RenderingStats(object):
106 def __init__(self, renderer_process, browser_process, timeline_ranges): 87 def __init__(self, renderer_process, browser_process, timeline_ranges):
107 """ 88 """
108 Utility class for extracting rendering statistics from the timeline (or 89 Utility class for extracting rendering statistics from the timeline (or
109 other loggin facilities), and providing them in a common format to classes 90 other loggin facilities), and providing them in a common format to classes
110 that compute benchmark metrics from this data. 91 that compute benchmark metrics from this data.
111 92
112 Stats are lists of lists of numbers. The outer list stores one list per 93 Stats are lists of lists of numbers. The outer list stores one list per
113 timeline range. 94 timeline range.
114 95
115 All *_time values are measured in milliseconds. 96 All *_time values are measured in milliseconds.
116 """ 97 """
117 assert(len(timeline_ranges) > 0) 98 assert(len(timeline_ranges) > 0)
118 # Find the top level process with rendering stats (browser or renderer). 99 self.renderer_process = renderer_process
119 if HasRenderingStats(browser_process):
120 self.top_level_process = browser_process
121 else:
122 self.top_level_process = renderer_process
123 100
124 self.frame_timestamps = [] 101 self.frame_timestamps = []
125 self.frame_times = [] 102 self.frame_times = []
126 self.paint_times = [] 103 self.paint_times = []
127 self.painted_pixel_counts = [] 104 self.painted_pixel_counts = []
128 self.record_times = [] 105 self.record_times = []
129 self.recorded_pixel_counts = [] 106 self.recorded_pixel_counts = []
130 self.rasterize_times = [] 107 self.rasterize_times = []
131 self.rasterized_pixel_counts = [] 108 self.rasterized_pixel_counts = []
132 # End-to-end latency for MouseWheel scroll - from when mouse wheel event is 109 # End-to-end latency for MouseWheel scroll - from when mouse wheel event is
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 self.touch_scroll_latency = ComputeTouchScrollLatency(touch_scroll_events) 146 self.touch_scroll_latency = ComputeTouchScrollLatency(touch_scroll_events)
170 147
171 js_touch_scroll_events = GetScrollInputLatencyEvents( 148 js_touch_scroll_events = GetScrollInputLatencyEvents(
172 "TouchMove", browser_process, timeline_range) 149 "TouchMove", browser_process, timeline_range)
173 self.js_touch_scroll_latency = ComputeTouchScrollLatency( 150 self.js_touch_scroll_latency = ComputeTouchScrollLatency(
174 js_touch_scroll_events) 151 js_touch_scroll_events)
175 152
176 def initMainThreadStatsFromTimeline(self, timeline_range): 153 def initMainThreadStatsFromTimeline(self, timeline_range):
177 event_name = 'BenchmarkInstrumentation::MainThreadRenderingStats' 154 event_name = 'BenchmarkInstrumentation::MainThreadRenderingStats'
178 events = [] 155 events = []
179 for event in self.top_level_process.IterAllSlicesOfName(event_name): 156 for event in self.renderer_process.IterAllSlicesOfName(event_name):
180 if event.start >= timeline_range.min and event.end <= timeline_range.max: 157 if event.start >= timeline_range.min and event.end <= timeline_range.max:
181 if 'data' not in event.args: 158 if 'data' not in event.args:
182 continue 159 continue
183 events.append(event) 160 events.append(event)
184 events.sort(key=attrgetter('start')) 161 events.sort(key=attrgetter('start'))
185 162
186 first_frame = True 163 first_frame = True
187 for event in events: 164 for event in events:
188 frame_count = event.args['data']['frame_count'] 165 frame_count = event.args['data']['frame_count']
189 if frame_count > 1: 166 if frame_count > 1:
(...skipping 10 matching lines...) Expand all
200 self.painted_pixel_counts[-1].append( 177 self.painted_pixel_counts[-1].append(
201 event.args['data']['painted_pixel_count']) 178 event.args['data']['painted_pixel_count'])
202 self.record_times[-1].append(1000.0 * 179 self.record_times[-1].append(1000.0 *
203 event.args['data']['record_time']) 180 event.args['data']['record_time'])
204 self.recorded_pixel_counts[-1].append( 181 self.recorded_pixel_counts[-1].append(
205 event.args['data']['recorded_pixel_count']) 182 event.args['data']['recorded_pixel_count'])
206 183
207 def initImplThreadStatsFromTimeline(self, timeline_range): 184 def initImplThreadStatsFromTimeline(self, timeline_range):
208 event_name = 'BenchmarkInstrumentation::ImplThreadRenderingStats' 185 event_name = 'BenchmarkInstrumentation::ImplThreadRenderingStats'
209 events = [] 186 events = []
210 for event in self.top_level_process.IterAllSlicesOfName(event_name): 187 for event in self.renderer_process.IterAllSlicesOfName(event_name):
211 if event.start >= timeline_range.min and event.end <= timeline_range.max: 188 if event.start >= timeline_range.min and event.end <= timeline_range.max:
212 if 'data' not in event.args: 189 if 'data' not in event.args:
213 continue 190 continue
214 events.append(event) 191 events.append(event)
215 events.sort(key=attrgetter('start')) 192 events.sort(key=attrgetter('start'))
216 193
217 first_frame = True 194 first_frame = True
218 for event in events: 195 for event in events:
219 frame_count = event.args['data']['frame_count'] 196 frame_count = event.args['data']['frame_count']
220 if frame_count > 1: 197 if frame_count > 1:
221 raise ValueError, 'trace contains multi-frame render stats' 198 raise ValueError, 'trace contains multi-frame render stats'
222 if frame_count == 1: 199 if frame_count == 1:
223 self.frame_timestamps[-1].append( 200 self.frame_timestamps[-1].append(
224 event.start) 201 event.start)
225 if not first_frame: 202 if not first_frame:
226 self.frame_times[-1].append(round(self.frame_timestamps[-1][-1] - 203 self.frame_times[-1].append(round(self.frame_timestamps[-1][-1] -
227 self.frame_timestamps[-1][-2], 2)) 204 self.frame_timestamps[-1][-2], 2))
228 first_frame = False 205 first_frame = False
229 self.rasterize_times[-1].append(1000.0 * 206 self.rasterize_times[-1].append(1000.0 *
230 event.args['data']['rasterize_time']) 207 event.args['data']['rasterize_time'])
231 self.rasterized_pixel_counts[-1].append( 208 self.rasterized_pixel_counts[-1].append(
232 event.args['data']['rasterized_pixel_count']) 209 event.args['data']['rasterized_pixel_count'])
OLDNEW
« no previous file with comments | « no previous file | tools/perf/metrics/rendering_stats_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698