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

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

Issue 132433004: Collecting LatencyInfo in telemetry (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: fix presubmit error "unused variable" Created 6 years, 10 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
« no previous file with comments | « tools/perf/metrics/rendering_stats.py ('k') | tools/perf/metrics/smoothness.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 import random 5 import random
6 import unittest 6 import unittest
7 7
8 from metrics.rendering_stats import UI_COMP_NAME, BEGIN_COMP_NAME, END_COMP_NAME
9 from metrics.rendering_stats import GetScrollInputLatencyEvents
10 from metrics.rendering_stats import ComputeMouseWheelScrollLatency
11 from metrics.rendering_stats import ComputeTouchScrollLatency
8 from metrics.rendering_stats import RenderingStats 12 from metrics.rendering_stats import RenderingStats
9 import telemetry.core.timeline.bounds as timeline_bounds 13 import telemetry.core.timeline.bounds as timeline_bounds
10 from telemetry.core.timeline import model 14 from telemetry.core.timeline import model
15 import telemetry.core.timeline.async_slice as tracing_async_slice
11 16
12 17
13 class MockTimer(object): 18 class MockTimer(object):
14 """A mock timer class which can generate random durations. 19 """A mock timer class which can generate random durations.
15 20
16 An instance of this class is used as a global timer to generate random 21 An instance of this class is used as a global timer to generate random
17 durations for stats and consistent timestamps for all mock trace events. 22 durations for stats and consistent timestamps for all mock trace events.
18 The unit of time is milliseconds. 23 The unit of time is milliseconds.
19 """ 24 """
20 def __init__(self): 25 def __init__(self):
(...skipping 23 matching lines...) Expand all
44 def AppendNewRange(self): 49 def AppendNewRange(self):
45 self.frame_timestamps.append([]) 50 self.frame_timestamps.append([])
46 self.frame_times.append([]) 51 self.frame_times.append([])
47 self.paint_times.append([]) 52 self.paint_times.append([])
48 self.painted_pixel_counts.append([]) 53 self.painted_pixel_counts.append([])
49 self.record_times.append([]) 54 self.record_times.append([])
50 self.recorded_pixel_counts.append([]) 55 self.recorded_pixel_counts.append([])
51 self.rasterize_times.append([]) 56 self.rasterize_times.append([])
52 self.rasterized_pixel_counts.append([]) 57 self.rasterized_pixel_counts.append([])
53 58
59 class ReferenceInputLatencyStats(object):
60 """ Stores expected data for comparison with actual input latency stats """
61 def __init__(self):
62 self.mouse_wheel_scroll_latency = []
63 self.touch_scroll_latency = []
64 self.mouse_wheel_scroll_events = []
65 self.touch_scroll_events = []
54 66
55 def AddMainThreadRenderingStats(mock_timer, thread, first_frame, 67 def AddMainThreadRenderingStats(mock_timer, thread, first_frame,
56 ref_stats = None): 68 ref_stats = None):
57 """ Adds a random main thread rendering stats event. 69 """ Adds a random main thread rendering stats event.
58 70
59 thread: The timeline model thread to which the event will be added. 71 thread: The timeline model thread to which the event will be added.
60 first_frame: Is this the first frame within the bounds of an action? 72 first_frame: Is this the first frame within the bounds of an action?
61 ref_stats: A ReferenceRenderingStats object to record expected values. 73 ref_stats: A ReferenceRenderingStats object to record expected values.
62 """ 74 """
63 # Create randonm data and timestap for main thread rendering stats. 75 # Create randonm data and timestap for main thread rendering stats.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 # Add frame_time if this is not the first frame in within the bounds of an 133 # Add frame_time if this is not the first frame in within the bounds of an
122 # action. 134 # action.
123 prev_timestamp = ref_stats.frame_timestamps[-1][-1] 135 prev_timestamp = ref_stats.frame_timestamps[-1][-1]
124 ref_stats.frame_times[-1].append(round(timestamp - prev_timestamp, 2)) 136 ref_stats.frame_times[-1].append(round(timestamp - prev_timestamp, 2))
125 ref_stats.frame_timestamps[-1].append(timestamp) 137 ref_stats.frame_timestamps[-1].append(timestamp)
126 138
127 ref_stats.rasterize_times[-1].append(data['rasterize_time'] * 1000.0) 139 ref_stats.rasterize_times[-1].append(data['rasterize_time'] * 1000.0)
128 ref_stats.rasterized_pixel_counts[-1].append(data['rasterized_pixel_count']) 140 ref_stats.rasterized_pixel_counts[-1].append(data['rasterized_pixel_count'])
129 141
130 142
143 def AddInputLatencyStats(mock_timer, input_type, start_thread, end_thread,
144 ref_latency_stats = None):
145 """ Adds a random input latency stats event.
146
147 input_type: The input type for which the latency slice is generated.
148 start_thread: The start thread on which the async slice is added.
149 end_thread: The end thread on which the async slice is ended.
150 ref_latency_stats: A ReferenceInputLatencyStats object for expected values.
151 """
152
153 mock_timer.Advance()
154 ui_comp_time = mock_timer.Get() * 1000.0
155 mock_timer.Advance()
156 begin_comp_time = mock_timer.Get() * 1000.0
157 mock_timer.Advance(10, 20)
158 end_comp_time = mock_timer.Get() * 1000.0
159
160 data = { UI_COMP_NAME: {'time': ui_comp_time},
161 BEGIN_COMP_NAME: {'time': begin_comp_time},
162 END_COMP_NAME: {'time': end_comp_time} }
163
164 timestamp = mock_timer.Get()
165
166 async_slice = tracing_async_slice.AsyncSlice(
167 'benchmark', 'InputLatency', timestamp)
168
169 async_sub_slice = tracing_async_slice.AsyncSlice(
170 'benchmark', 'InputLatency', timestamp)
171 async_sub_slice.args = {'data': data, 'step': input_type}
172 async_sub_slice.parent_slice = async_slice
173 async_sub_slice.start_thread = start_thread
174 async_sub_slice.end_thread = end_thread
175
176 async_slice.sub_slices.append(async_sub_slice)
177 async_slice.start_thread = start_thread
178 async_slice.end_thread = end_thread
179 start_thread.AddAsyncSlice(async_slice)
180
181 if not ref_latency_stats:
182 return
183
184 if input_type == 'MouseWheel':
185 ref_latency_stats.mouse_wheel_scroll_events.append(async_sub_slice)
186 ref_latency_stats.mouse_wheel_scroll_latency.append(
187 (data[END_COMP_NAME]['time'] - data[BEGIN_COMP_NAME]['time']) / 1000.0)
188
189
190 if input_type == 'GestureScrollUpdate':
191 ref_latency_stats.touch_scroll_events.append(async_sub_slice)
192 ref_latency_stats.touch_scroll_latency.append(
193 (data[END_COMP_NAME]['time'] - data[UI_COMP_NAME]['time']) / 1000.0)
194
131 class RenderingStatsUnitTest(unittest.TestCase): 195 class RenderingStatsUnitTest(unittest.TestCase):
132 def testFromTimeline(self): 196 def testFromTimeline(self):
133 timeline = model.TimelineModel() 197 timeline = model.TimelineModel()
134 198
135 # Create a browser process and a renderer process, and a main thread and 199 # Create a browser process and a renderer process, and a main thread and
136 # impl thread for each. 200 # impl thread for each.
137 browser = timeline.GetOrCreateProcess(pid = 1) 201 browser = timeline.GetOrCreateProcess(pid = 1)
138 browser_main = browser.GetOrCreateThread(tid = 11) 202 browser_main = browser.GetOrCreateThread(tid = 11)
139 browser_compositor = browser.GetOrCreateThread(tid = 12) 203 browser_compositor = browser.GetOrCreateThread(tid = 12)
140 renderer = timeline.GetOrCreateProcess(pid = 2) 204 renderer = timeline.GetOrCreateProcess(pid = 2)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 AddImplThreadRenderingStats(timer, browser_compositor, first, None) 252 AddImplThreadRenderingStats(timer, browser_compositor, first, None)
189 renderer_main.EndSlice(timer.Get()) 253 renderer_main.EndSlice(timer.Get())
190 254
191 renderer_main.FinalizeImport() 255 renderer_main.FinalizeImport()
192 renderer_compositor.FinalizeImport() 256 renderer_compositor.FinalizeImport()
193 257
194 timeline_markers = timeline.FindTimelineMarkers( 258 timeline_markers = timeline.FindTimelineMarkers(
195 ['ActionA', 'ActionB', 'ActionA']) 259 ['ActionA', 'ActionB', 'ActionA'])
196 timeline_ranges = [ timeline_bounds.Bounds.CreateFromEvent(marker) 260 timeline_ranges = [ timeline_bounds.Bounds.CreateFromEvent(marker)
197 for marker in timeline_markers ] 261 for marker in timeline_markers ]
198 stats = RenderingStats(renderer, timeline_ranges) 262 stats = RenderingStats(renderer, browser, timeline_ranges)
199 263
200 # Compare rendering stats to reference. 264 # Compare rendering stats to reference.
201 self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps) 265 self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps)
202 self.assertEquals(stats.frame_times, ref_stats.frame_times) 266 self.assertEquals(stats.frame_times, ref_stats.frame_times)
203 self.assertEquals(stats.rasterize_times, ref_stats.rasterize_times) 267 self.assertEquals(stats.rasterize_times, ref_stats.rasterize_times)
204 self.assertEquals(stats.rasterized_pixel_counts, 268 self.assertEquals(stats.rasterized_pixel_counts,
205 ref_stats.rasterized_pixel_counts) 269 ref_stats.rasterized_pixel_counts)
206 self.assertEquals(stats.paint_times, ref_stats.paint_times) 270 self.assertEquals(stats.paint_times, ref_stats.paint_times)
207 self.assertEquals(stats.painted_pixel_counts, 271 self.assertEquals(stats.painted_pixel_counts,
208 ref_stats.painted_pixel_counts) 272 ref_stats.painted_pixel_counts)
209 self.assertEquals(stats.record_times, ref_stats.record_times) 273 self.assertEquals(stats.record_times, ref_stats.record_times)
210 self.assertEquals(stats.recorded_pixel_counts, 274 self.assertEquals(stats.recorded_pixel_counts,
211 ref_stats.recorded_pixel_counts) 275 ref_stats.recorded_pixel_counts)
276
277 def testScrollLatencyFromTimeline(self):
278 timeline = model.TimelineModel()
279
280 # Create a browser process and a renderer process.
281 browser = timeline.GetOrCreateProcess(pid = 1)
282 browser_main = browser.GetOrCreateThread(tid = 11)
283 renderer = timeline.GetOrCreateProcess(pid = 2)
284 renderer_main = renderer.GetOrCreateThread(tid = 21)
285
286 timer = MockTimer()
287 ref_latency_stats = ReferenceInputLatencyStats()
288
289 # Create 10 input latency stats events for Action A.
290 timer.Advance()
291 renderer_main.BeginSlice('webkit.console', 'ActionA', timer.Get(), '')
292 for _ in xrange(0, 10):
293 AddInputLatencyStats(timer, 'MouseWheel', browser_main,
294 renderer_main, ref_latency_stats)
295 AddInputLatencyStats(timer, 'GestureScrollUpdate', browser_main,
296 renderer_main, ref_latency_stats)
297 renderer_main.EndSlice(timer.Get())
298
299 # Create 5 input latency stats events not within any action.
300 for _ in xrange(0, 5):
301 AddInputLatencyStats(timer, 'MouseWheel', browser_main,
302 renderer_main, None)
303 AddInputLatencyStats(timer, 'GestureScrollUpdate', browser_main,
304 renderer_main, None)
305
306 # Create 10 input latency stats events for Action B.
307 timer.Advance()
308 renderer_main.BeginSlice('webkit.console', 'ActionB', timer.Get(), '')
309 for _ in xrange(0, 10):
310 AddInputLatencyStats(timer, 'MouseWheel', browser_main,
311 renderer_main, ref_latency_stats)
312 AddInputLatencyStats(timer, 'GestureScrollUpdate', browser_main,
313 renderer_main, ref_latency_stats)
314 renderer_main.EndSlice(timer.Get())
315
316 # Create 10 input latency stats events for Action A.
317 timer.Advance()
318 renderer_main.BeginSlice('webkit.console', 'ActionA', timer.Get(), '')
319 for _ in xrange(0, 10):
320 AddInputLatencyStats(timer, 'MouseWheel', browser_main,
321 renderer_main, ref_latency_stats)
322 AddInputLatencyStats(timer, 'GestureScrollUpdate', browser_main,
323 renderer_main, ref_latency_stats)
324 renderer_main.EndSlice(timer.Get())
325
326 browser_main.FinalizeImport()
327 renderer_main.FinalizeImport()
328
329 mouse_wheel_scroll_events = []
330 touch_scroll_events = []
331
332 timeline_markers = timeline.FindTimelineMarkers(
333 ['ActionA', 'ActionB', 'ActionA'])
334 for timeline_range in [ timeline_bounds.Bounds.CreateFromEvent(marker)
335 for marker in timeline_markers ]:
336 if timeline_range.is_empty:
337 continue
338 tmp_mouse_events, tmp_touch_events = GetScrollInputLatencyEvents(
339 browser, timeline_range)
340 mouse_wheel_scroll_events.extend(tmp_mouse_events)
341 touch_scroll_events.extend(tmp_touch_events)
342
343 self.assertEquals(mouse_wheel_scroll_events,
344 ref_latency_stats.mouse_wheel_scroll_events)
345 self.assertEquals(touch_scroll_events,
346 ref_latency_stats.touch_scroll_events)
347 self.assertEquals(ComputeMouseWheelScrollLatency(mouse_wheel_scroll_events),
348 ref_latency_stats.mouse_wheel_scroll_latency)
349 self.assertEquals(ComputeTouchScrollLatency(touch_scroll_events),
350 ref_latency_stats.touch_scroll_latency)
OLDNEW
« no previous file with comments | « tools/perf/metrics/rendering_stats.py ('k') | tools/perf/metrics/smoothness.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698