OLD | NEW |
(Empty) | |
| 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 |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import random |
| 6 import unittest |
| 7 |
| 8 from metrics.rendering_stats import RenderingStats |
| 9 from telemetry.core.timeline import model |
| 10 |
| 11 |
| 12 class MockTimer(object): |
| 13 """A mock timer class which can generate random durations. |
| 14 |
| 15 An instance of this class is used as a global timer to generate random |
| 16 durations for stats and consistent timestamps for all mock trace events. |
| 17 The unit of time is milliseconds. |
| 18 """ |
| 19 def __init__(self): |
| 20 self.milliseconds = 0 |
| 21 |
| 22 def Get(self): |
| 23 return self.milliseconds |
| 24 |
| 25 def Advance(self, low=0, high=1): |
| 26 delta = random.uniform(low, high) |
| 27 self.milliseconds += delta |
| 28 return delta |
| 29 |
| 30 |
| 31 class ReferenceRenderingStats(object): |
| 32 """ Stores expected data for comparison with actual RenderingStats """ |
| 33 def __init__(self): |
| 34 self.frame_timestamps = [] |
| 35 self.frame_times = [] |
| 36 self.paint_time = [] |
| 37 self.painted_pixel_count = [] |
| 38 self.record_time = [] |
| 39 self.recorded_pixel_count = [] |
| 40 self.rasterize_time = [] |
| 41 self.rasterized_pixel_count = [] |
| 42 |
| 43 |
| 44 def AddMainThreadRenderingStats(mock_timer, thread, first_frame, |
| 45 ref_stats = None): |
| 46 """ Adds a random main thread rendering stats event. |
| 47 |
| 48 thread: The timeline model thread to which the event will be added. |
| 49 first_frame: Is this the first frame within the bounds of an action? |
| 50 ref_stats: A ReferenceRenderingStats object to record expected values. |
| 51 """ |
| 52 # Create randonm data and timestap for main thread rendering stats. |
| 53 data = { 'frame_count': 0, |
| 54 'paint_time': 0.0, |
| 55 'painted_pixel_count': 0, |
| 56 'record_time': mock_timer.Advance(2, 4) / 1000.0, |
| 57 'recorded_pixel_count': 3000*3000 } |
| 58 timestamp = mock_timer.Get() |
| 59 |
| 60 # Add a slice with the event data to the given thread. |
| 61 thread.PushCompleteSlice( |
| 62 'benchmark', 'BenchmarkInstrumentation::MainThreadRenderingStats', |
| 63 timestamp, 0.0, {'data': data}) |
| 64 |
| 65 if not ref_stats: |
| 66 return |
| 67 |
| 68 # Add timestamp only if a frame was output |
| 69 if data['frame_count'] == 1: |
| 70 if not first_frame: |
| 71 # Add frame_time if this is not the first frame in within the bounds of an |
| 72 # action. |
| 73 prev_timestamp = ref_stats.frame_timestamps[-1] |
| 74 ref_stats.frame_times.append(round(timestamp - prev_timestamp, 2)) |
| 75 ref_stats.frame_timestamps.append(timestamp) |
| 76 |
| 77 ref_stats.paint_time.append(data['paint_time'] * 1000.0) |
| 78 ref_stats.painted_pixel_count.append(data['painted_pixel_count']) |
| 79 ref_stats.record_time.append(data['record_time'] * 1000.0) |
| 80 ref_stats.recorded_pixel_count.append(data['recorded_pixel_count']) |
| 81 |
| 82 |
| 83 def AddImplThreadRenderingStats(mock_timer, thread, first_frame, |
| 84 ref_stats = None): |
| 85 """ Adds a random impl thread rendering stats event. |
| 86 |
| 87 thread: The timeline model thread to which the event will be added. |
| 88 first_frame: Is this the first frame within the bounds of an action? |
| 89 ref_stats: A ReferenceRenderingStats object to record expected values. |
| 90 """ |
| 91 # Create randonm data and timestap for impl thread rendering stats. |
| 92 data = { 'frame_count': 1, |
| 93 'rasterize_time': mock_timer.Advance(5, 10) / 1000.0, |
| 94 'rasterized_pixel_count': 1280*720 } |
| 95 timestamp = mock_timer.Get() |
| 96 |
| 97 # Add a slice with the event data to the given thread. |
| 98 thread.PushCompleteSlice( |
| 99 'benchmark', 'BenchmarkInstrumentation::ImplThreadRenderingStats', |
| 100 timestamp, 0.0, {'data': data}) |
| 101 |
| 102 if not ref_stats: |
| 103 return |
| 104 |
| 105 # Add timestamp only if a frame was output |
| 106 if data['frame_count'] == 1: |
| 107 if not first_frame: |
| 108 # Add frame_time if this is not the first frame in within the bounds of an |
| 109 # action. |
| 110 prev_timestamp = ref_stats.frame_timestamps[-1] |
| 111 ref_stats.frame_times.append(round(timestamp - prev_timestamp, 2)) |
| 112 ref_stats.frame_timestamps.append(timestamp) |
| 113 |
| 114 ref_stats.rasterize_time.append(data['rasterize_time'] * 1000.0) |
| 115 ref_stats.rasterized_pixel_count.append(data['rasterized_pixel_count']) |
| 116 |
| 117 |
| 118 class RenderingStatsUnitTest(unittest.TestCase): |
| 119 def testFromTimeline(self): |
| 120 timeline = model.TimelineModel() |
| 121 |
| 122 # Create a browser process and a renderer process, and a main thread and |
| 123 # impl thread for each. |
| 124 browser = timeline.GetOrCreateProcess(pid = 1) |
| 125 browser_main = browser.GetOrCreateThread(tid = 11) |
| 126 browser_compositor = browser.GetOrCreateThread(tid = 12) |
| 127 renderer = timeline.GetOrCreateProcess(pid = 2) |
| 128 renderer_main = renderer.GetOrCreateThread(tid = 21) |
| 129 renderer_compositor = renderer.GetOrCreateThread(tid = 22) |
| 130 |
| 131 timer = MockTimer() |
| 132 ref_stats = ReferenceRenderingStats() |
| 133 |
| 134 # Create 10 main and impl rendering stats events for Action A. |
| 135 timer.Advance() |
| 136 renderer_main.BeginSlice('webkit.console', 'ActionA', timer.Get(), '') |
| 137 for i in xrange(0, 10): |
| 138 first = (i == 0) |
| 139 AddMainThreadRenderingStats(timer, renderer_main, first, ref_stats) |
| 140 AddImplThreadRenderingStats(timer, renderer_compositor, first, ref_stats) |
| 141 AddMainThreadRenderingStats(timer, browser_main, first, None) |
| 142 AddImplThreadRenderingStats(timer, browser_compositor, first, None) |
| 143 renderer_main.EndSlice(timer.Get()) |
| 144 |
| 145 # Create 5 main and impl rendering stats events not within any action. |
| 146 for i in xrange(0, 5): |
| 147 first = (i == 0) |
| 148 AddMainThreadRenderingStats(timer, renderer_main, first, None) |
| 149 AddImplThreadRenderingStats(timer, renderer_compositor, first, None) |
| 150 AddMainThreadRenderingStats(timer, browser_main, first, None) |
| 151 AddImplThreadRenderingStats(timer, browser_compositor, first, None) |
| 152 |
| 153 # Create 10 main and impl rendering stats events for Action B. |
| 154 timer.Advance() |
| 155 renderer_main.BeginSlice('webkit.console', 'ActionB', timer.Get(), '') |
| 156 for i in xrange(0, 10): |
| 157 first = (i == 0) |
| 158 AddMainThreadRenderingStats(timer, renderer_main, first, ref_stats) |
| 159 AddImplThreadRenderingStats(timer, renderer_compositor, first, ref_stats) |
| 160 AddMainThreadRenderingStats(timer, browser_main, first, None) |
| 161 AddImplThreadRenderingStats(timer, browser_compositor, first, None) |
| 162 renderer_main.EndSlice(timer.Get()) |
| 163 |
| 164 # Create 10 main and impl rendering stats events for Action A. |
| 165 timer.Advance() |
| 166 renderer_main.BeginSlice('webkit.console', 'ActionA', timer.Get(), '') |
| 167 for i in xrange(0, 10): |
| 168 first = (i == 0) |
| 169 AddMainThreadRenderingStats(timer, renderer_main, first, ref_stats) |
| 170 AddImplThreadRenderingStats(timer, renderer_compositor, first, ref_stats) |
| 171 AddMainThreadRenderingStats(timer, browser_main, first, None) |
| 172 AddImplThreadRenderingStats(timer, browser_compositor, first, None) |
| 173 renderer_main.EndSlice(timer.Get()) |
| 174 |
| 175 renderer_main.FinalizeImport() |
| 176 renderer_compositor.FinalizeImport() |
| 177 |
| 178 timeline_markers = timeline.FindTimelineMarkers( |
| 179 ['ActionA', 'ActionB', 'ActionA']) |
| 180 stats = RenderingStats(renderer, timeline_markers) |
| 181 |
| 182 # Compare rendering stats to reference. |
| 183 self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps) |
| 184 self.assertEquals(stats.frame_times, ref_stats.frame_times) |
| 185 self.assertEquals(stats.rasterize_time, ref_stats.rasterize_time) |
| 186 self.assertEquals(stats.rasterized_pixel_count, |
| 187 ref_stats.rasterized_pixel_count) |
| 188 self.assertEquals(stats.paint_time, ref_stats.paint_time) |
| 189 self.assertEquals(stats.painted_pixel_count, ref_stats.painted_pixel_count) |
| 190 self.assertEquals(stats.record_time, ref_stats.record_time) |
| 191 self.assertEquals(stats.recorded_pixel_count, |
| 192 ref_stats.recorded_pixel_count) |
OLD | NEW |