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 import random | 5 import random |
6 import unittest | 6 import unittest |
7 | 7 |
8 from metrics import smoothness | 8 from metrics import smoothness |
9 from metrics import statistics | 9 from metrics import statistics |
10 from metrics.gpu_rendering_stats import GpuRenderingStats | 10 from metrics.rendering_stats import RenderingStats |
11 from telemetry.core.backends.chrome.tracing_backend import RawTraceResultImpl | 11 from telemetry.core.backends.chrome.tracing_backend import RawTraceResultImpl |
12 from telemetry.core.backends.chrome.trace_result import TraceResult | 12 from telemetry.core.backends.chrome.trace_result import TraceResult |
13 from telemetry.page import page | 13 from telemetry.page import page |
14 from telemetry.page.page_measurement_results import PageMeasurementResults | 14 from telemetry.page.page_measurement_results import PageMeasurementResults |
15 | 15 |
16 | 16 |
17 class MockTimer(object): | 17 class MockTimer(object): |
18 """A mock timer class which can generate random durations. | 18 """A mock timer class which can generate random durations. |
19 | 19 |
20 An instance of this class is used as a global timer to generate random | 20 An instance of this class is used as a global timer to generate random |
(...skipping 10 matching lines...) Expand all Loading... |
31 | 31 |
32 class MockFrame(object): | 32 class MockFrame(object): |
33 """Mocks rendering, texture and latency stats for a single frame.""" | 33 """Mocks rendering, texture and latency stats for a single frame.""" |
34 def __init__(self, mock_timer): | 34 def __init__(self, mock_timer): |
35 """ Initialize the stats to random values """ | 35 """ Initialize the stats to random values """ |
36 self.start = mock_timer.microseconds | 36 self.start = mock_timer.microseconds |
37 self.main_stats = {} | 37 self.main_stats = {} |
38 self.impl_stats = {} | 38 self.impl_stats = {} |
39 self.texture_stats = {} | 39 self.texture_stats = {} |
40 self.latency_stats = {} | 40 self.latency_stats = {} |
41 self.main_stats['animation_frame_count'] = 0 | 41 self.main_stats['frame_count'] = 0 |
42 self.main_stats['screen_frame_count'] = 0 | |
43 self.main_stats['paint_time'] = mock_timer.Advance() | 42 self.main_stats['paint_time'] = mock_timer.Advance() |
| 43 self.main_stats['painted_pixel_count'] = random.randint(0, 2000000) |
44 self.main_stats['record_time'] = mock_timer.Advance() | 44 self.main_stats['record_time'] = mock_timer.Advance() |
45 self.main_stats['commit_time'] = mock_timer.Advance() | |
46 self.main_stats['commit_count'] = 1 | |
47 self.main_stats['painted_pixel_count'] = random.randint(0, 2000000) | |
48 self.main_stats['recorded_pixel_count'] = random.randint(0, 2000000) | 45 self.main_stats['recorded_pixel_count'] = random.randint(0, 2000000) |
49 self.main_stats['image_gathering_count'] = random.randint(0, 100) | 46 self.impl_stats['frame_count'] = 1 |
50 self.main_stats['image_gathering_time'] = mock_timer.Advance() | |
51 self.impl_stats['screen_frame_count'] = 1 | |
52 self.impl_stats['dropped_frame_count'] = random.randint(0, 4) | |
53 self.impl_stats['rasterize_time'] = mock_timer.Advance() | 47 self.impl_stats['rasterize_time'] = mock_timer.Advance() |
54 self.impl_stats['rasterize_time_for_now_bins_on_pending_tree'] = ( | |
55 mock_timer.Advance()) | |
56 self.impl_stats['best_rasterize_time'] = mock_timer.Advance() | |
57 self.impl_stats['rasterized_pixel_count'] = random.randint(0, 2000000) | 48 self.impl_stats['rasterized_pixel_count'] = random.randint(0, 2000000) |
58 self.impl_stats['impl_thread_scroll_count'] = random.randint(0, 4) | |
59 self.impl_stats['main_thread_scroll_count'] = random.randint(0, 4) | |
60 self.impl_stats['drawn_layer_count'] = random.randint(0, 10) | |
61 self.impl_stats['missing_tile_count'] = random.randint(0, 10000) | |
62 self.impl_stats['deferred_image_decode_count'] = random.randint(0, 100) | |
63 self.impl_stats['deferred_image_cache_hit_count'] = random.randint(0, 50) | |
64 self.impl_stats['tile_analysis_count'] = random.randint(0, 10000) | |
65 self.impl_stats['solid_color_tile_analysis_count'] = random.randint(0, 1000) | |
66 self.impl_stats['deferred_image_decode_time'] = mock_timer.Advance() | |
67 self.impl_stats['tile_analysis_time'] = mock_timer.Advance() | |
68 self.end = mock_timer.microseconds | 49 self.end = mock_timer.microseconds |
69 self.duration = self.end - self.start | 50 self.duration = self.end - self.start |
70 | 51 |
71 def AppendTraceEventForMainThreadStats(self, trace_events): | 52 def AppendTraceEventForMainThreadStats(self, trace_events): |
72 """Appends a trace event with the main thread stats. | 53 """Appends a trace event with the main thread stats. |
73 | 54 |
74 The trace event is a dict with the following keys: | 55 The trace event is a dict with the following keys: |
75 'name', | 56 'name', |
76 'tts' (thread timestamp), | 57 'tts' (thread timestamp), |
77 'pid' (process id), | 58 'pid' (process id), |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 'tid': 11, | 122 'tid': 11, |
142 'ph': 'S', | 123 'ph': 'S', |
143 'id': '0xabcde'}) | 124 'id': '0xabcde'}) |
144 | 125 |
145 # Generate 100 random mock frames and append their trace events. | 126 # Generate 100 random mock frames and append their trace events. |
146 for _ in xrange(0, 100): | 127 for _ in xrange(0, 100): |
147 mock_frame = MockFrame(mock_timer) | 128 mock_frame = MockFrame(mock_timer) |
148 mock_frame.AppendTraceEventForMainThreadStats(trace_events) | 129 mock_frame.AppendTraceEventForMainThreadStats(trace_events) |
149 mock_frame.AppendTraceEventForImplThreadStats(trace_events) | 130 mock_frame.AppendTraceEventForImplThreadStats(trace_events) |
150 total_time_seconds += mock_frame.duration / 1e6 | 131 total_time_seconds += mock_frame.duration / 1e6 |
151 num_frames_sent += mock_frame.main_stats['screen_frame_count'] | 132 num_frames_sent += mock_frame.main_stats['frame_count'] |
152 num_frames_sent += mock_frame.impl_stats['screen_frame_count'] | 133 num_frames_sent += mock_frame.impl_stats['frame_count'] |
153 current_frame_time = mock_timer.microseconds / 1000.0 | 134 current_frame_time = mock_timer.microseconds / 1000.0 |
154 if previous_frame_time: | 135 if previous_frame_time: |
155 difference = current_frame_time - previous_frame_time | 136 difference = current_frame_time - previous_frame_time |
156 difference = round(difference, 2) | 137 difference = round(difference, 2) |
157 expected_frame_times.append(difference) | 138 expected_frame_times.append(difference) |
158 previous_frame_time = current_frame_time | 139 previous_frame_time = current_frame_time |
159 | 140 |
160 # Append finish trace events for the timeline and gesture markers, in the | 141 # Append finish trace events for the timeline and gesture markers, in the |
161 # reverse order from how they were added, with some time in between. | 142 # reverse order from how they were added, with some time in between. |
162 trace_events.append({'name': smoothness.SYNTHETIC_GESTURE_MARKER, | 143 trace_events.append({'name': smoothness.SYNTHETIC_GESTURE_MARKER, |
(...skipping 15 matching lines...) Expand all Loading... |
178 'tid': 11, | 159 'tid': 11, |
179 'ph': 'F', | 160 'ph': 'F', |
180 'id': '0x12345'}) | 161 'id': '0x12345'}) |
181 | 162 |
182 # Create a timeline object from the trace. | 163 # Create a timeline object from the trace. |
183 trace_impl = RawTraceResultImpl(trace_events) | 164 trace_impl = RawTraceResultImpl(trace_events) |
184 trace_result = TraceResult(trace_impl) | 165 trace_result = TraceResult(trace_impl) |
185 timeline = trace_result.AsTimelineModel() | 166 timeline = trace_result.AsTimelineModel() |
186 | 167 |
187 # Find the timeline marker and gesture marker in the timeline, | 168 # Find the timeline marker and gesture marker in the timeline, |
188 # and create a GpuRenderingStats object. | 169 # and create a RenderingStats object. |
189 smoothness_marker = smoothness.FindTimelineMarker( | 170 smoothness_marker = smoothness.FindTimelineMarker( |
190 timeline, smoothness.TIMELINE_MARKER) | 171 timeline, smoothness.TIMELINE_MARKER) |
191 gesture_marker = smoothness.FindTimelineMarker( | 172 gesture_marker = smoothness.FindTimelineMarker( |
192 timeline, smoothness.SYNTHETIC_GESTURE_MARKER) | 173 timeline, smoothness.SYNTHETIC_GESTURE_MARKER) |
193 stats = GpuRenderingStats( | 174 stats = RenderingStats( |
194 smoothness_marker, gesture_marker, {}, True) | 175 smoothness_marker, gesture_marker, {}, True) |
195 | 176 |
196 # Make a results object and add results to it from the smoothness metric. | 177 # Make a results object and add results to it from the smoothness metric. |
197 res = PageMeasurementResults() | 178 res = PageMeasurementResults() |
198 res.WillMeasurePage(page.Page('http://foo.com/', None)) | 179 res.WillMeasurePage(page.Page('http://foo.com/', None)) |
199 smoothness.CalcResults(stats, res) | 180 smoothness.CalcResults(stats, res) |
200 res.DidMeasurePage() | 181 res.DidMeasurePage() |
201 | 182 |
202 self.assertEquals( | 183 self.assertEquals( |
203 expected_frame_times, | 184 expected_frame_times, |
204 res.page_results[0]['frame_times'].value) | 185 res.page_results[0]['frame_times'].value) |
205 self.assertAlmostEquals( | 186 self.assertAlmostEquals( |
206 1000.0 * (total_time_seconds / num_frames_sent), | 187 1000.0 * (total_time_seconds / num_frames_sent), |
207 res.page_results[0]['mean_frame_time'].value, | 188 res.page_results[0]['mean_frame_time'].value, |
208 places=2) | 189 places=2) |
209 | 190 |
210 # We don't verify the correctness of the discrepancy computation itself, | 191 # We don't verify the correctness of the discrepancy computation itself, |
211 # because we have a separate unit test for that purpose. | 192 # because we have a separate unit test for that purpose. |
212 self.assertAlmostEquals( | 193 self.assertAlmostEquals( |
213 statistics.FrameDiscrepancy(stats.screen_frame_timestamps, True), | 194 statistics.FrameDiscrepancy(stats.frame_timestamps, True), |
214 res.page_results[0]['jank'].value, | 195 res.page_results[0]['jank'].value, |
215 places=4) | 196 places=4) |
216 | 197 |
217 # We do not verify the correctness of Percentile here; Percentile should | 198 # We do not verify the correctness of Percentile here; Percentile should |
218 # have its own test. | 199 # have its own test. |
219 # The 17 here represents a threshold of 17 ms; this should match the value | 200 # The 17 here represents a threshold of 17 ms; this should match the value |
220 # in the smoothness metric. | 201 # in the smoothness metric. |
221 self.assertEquals( | 202 self.assertEquals( |
222 statistics.Percentile(expected_frame_times, 95.0) < 17.0, | 203 statistics.Percentile(expected_frame_times, 95.0) < 17.0, |
223 res.page_results[0]['mostly_smooth'].value) | 204 res.page_results[0]['mostly_smooth'].value) |
224 | |
OLD | NEW |