OLD | NEW |
(Empty) | |
| 1 # Copyright 2015 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 unittest |
| 6 |
| 7 from metrics import test_page_test_results |
| 8 from metrics import gpu_timeline |
| 9 from telemetry.timeline import async_slice |
| 10 from telemetry.timeline import model as model_module |
| 11 from telemetry.web_perf import timeline_interaction_record as tir_module |
| 12 |
| 13 FRAME_END_CATEGORY, FRAME_END_NAME = gpu_timeline.FRAME_END_MARKER |
| 14 INTERACTION_RECORDS = [tir_module.TimelineInteractionRecord("test-record", |
| 15 0, |
| 16 float('inf'))] |
| 17 |
| 18 |
| 19 def _CreateGPUAsyncSlices(name, start_time, duration, offset=0): |
| 20 args = { 'gl_category': gpu_timeline.TOPLEVEL_GL_CATEGORY } |
| 21 return (async_slice.AsyncSlice(gpu_timeline.TOPLEVEL_SERVICE_CATEGORY, |
| 22 name, start_time, |
| 23 args=args, |
| 24 duration=duration, |
| 25 thread_start=start_time), |
| 26 async_slice.AsyncSlice(gpu_timeline.TOPLEVEL_DEVICE_CATEGORY, |
| 27 name, start_time + offset, |
| 28 args=args, |
| 29 duration=duration, |
| 30 thread_start=start_time + offset)) |
| 31 |
| 32 |
| 33 class GPUTimelineTest(unittest.TestCase): |
| 34 def GetResults(self, metric, model, renderer_thread, interaction_records): |
| 35 results = test_page_test_results.TestPageTestResults(self) |
| 36 metric.AddResults(model, renderer_thread, interaction_records, results) |
| 37 return results |
| 38 |
| 39 def testExpectedResults(self): |
| 40 """Test a simply trace will output all expected results.""" |
| 41 model = model_module.TimelineModel() |
| 42 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 43 for slice_item in _CreateGPUAsyncSlices('test_item', 100, 10): |
| 44 test_thread.AddAsyncSlice(slice_item) |
| 45 model.FinalizeImport() |
| 46 |
| 47 metric = gpu_timeline.GPUTimelineMetric() |
| 48 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 49 interaction_records=INTERACTION_RECORDS) |
| 50 |
| 51 results.AssertHasPageSpecificScalarValue( |
| 52 'total_frame_max', 'ms', 10) |
| 53 results.AssertHasPageSpecificScalarValue( |
| 54 'total_frame_avg', 'ms', 10) |
| 55 results.AssertHasPageSpecificScalarValue( |
| 56 'total_frame_stddev', 'ms', 0) |
| 57 results.AssertHasPageSpecificScalarValue( |
| 58 'total_gpu_service_max', 'ms', 10) |
| 59 results.AssertHasPageSpecificScalarValue( |
| 60 'total_gpu_service_avg', 'ms', 10) |
| 61 results.AssertHasPageSpecificScalarValue( |
| 62 'total_gpu_service_stddev', 'ms', 0) |
| 63 results.AssertHasPageSpecificScalarValue( |
| 64 'total_gpu_device_max', 'ms', 10) |
| 65 results.AssertHasPageSpecificScalarValue( |
| 66 'total_gpu_device_avg', 'ms', 10) |
| 67 results.AssertHasPageSpecificScalarValue( |
| 68 'total_gpu_device_stddev', 'ms', 0) |
| 69 |
| 70 for tracked_name in gpu_timeline.TRACKED_NAMES.values(): |
| 71 results.AssertHasPageSpecificScalarValue( |
| 72 tracked_name + '_service_max', 'ms', 0) |
| 73 results.AssertHasPageSpecificScalarValue( |
| 74 tracked_name + '_service_avg', 'ms', 0) |
| 75 results.AssertHasPageSpecificScalarValue( |
| 76 tracked_name + '_service_stddev', 'ms', 0) |
| 77 results.AssertHasPageSpecificScalarValue( |
| 78 tracked_name + '_device_max', 'ms', 0) |
| 79 results.AssertHasPageSpecificScalarValue( |
| 80 tracked_name + '_device_avg', 'ms', 0) |
| 81 results.AssertHasPageSpecificScalarValue( |
| 82 tracked_name + '_device_stddev', 'ms', 0) |
| 83 |
| 84 def testNoDeviceTraceResults(self): |
| 85 """Test expected results when missing device traces.""" |
| 86 model = model_module.TimelineModel() |
| 87 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 88 service_slice, _ = _CreateGPUAsyncSlices('test_item', 100, 10) |
| 89 test_thread.AddAsyncSlice(service_slice) |
| 90 model.FinalizeImport() |
| 91 |
| 92 metric = gpu_timeline.GPUTimelineMetric() |
| 93 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 94 interaction_records=INTERACTION_RECORDS) |
| 95 |
| 96 results.AssertHasPageSpecificScalarValue( |
| 97 'total_frame_max', 'ms', 10) |
| 98 results.AssertHasPageSpecificScalarValue( |
| 99 'total_frame_avg', 'ms', 10) |
| 100 results.AssertHasPageSpecificScalarValue( |
| 101 'total_frame_stddev', 'ms', 0) |
| 102 results.AssertHasPageSpecificScalarValue( |
| 103 'total_gpu_service_max', 'ms', 10) |
| 104 results.AssertHasPageSpecificScalarValue( |
| 105 'total_gpu_service_avg', 'ms', 10) |
| 106 results.AssertHasPageSpecificScalarValue( |
| 107 'total_gpu_service_stddev', 'ms', 0) |
| 108 self.assertRaises(AssertionError, results.GetPageSpecificValueNamed, |
| 109 'total_gpu_device_max') |
| 110 self.assertRaises(AssertionError, results.GetPageSpecificValueNamed, |
| 111 'total_gpu_device_avg') |
| 112 self.assertRaises(AssertionError, results.GetPageSpecificValueNamed, |
| 113 'total_gpu_device_stddev') |
| 114 |
| 115 for tracked_name in gpu_timeline.TRACKED_NAMES.values(): |
| 116 results.AssertHasPageSpecificScalarValue( |
| 117 tracked_name + '_service_max', 'ms', 0) |
| 118 results.AssertHasPageSpecificScalarValue( |
| 119 tracked_name + '_service_avg', 'ms', 0) |
| 120 results.AssertHasPageSpecificScalarValue( |
| 121 tracked_name + '_service_stddev', 'ms', 0) |
| 122 self.assertRaises(AssertionError, results.GetPageSpecificValueNamed, |
| 123 tracked_name + '_device_max') |
| 124 self.assertRaises(AssertionError, results.GetPageSpecificValueNamed, |
| 125 tracked_name + '_device_avg') |
| 126 self.assertRaises(AssertionError, results.GetPageSpecificValueNamed, |
| 127 tracked_name + '_device_stddev') |
| 128 |
| 129 def testMismatchServiceDeviceCountsAsserts(self): |
| 130 """Test extra GPU service traces will cause a mismatch assertion.""" |
| 131 model = model_module.TimelineModel() |
| 132 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 133 for index in xrange(100): |
| 134 service_item, device_item = _CreateGPUAsyncSlices('test_item', 100, 10) |
| 135 test_thread.AddAsyncSlice(service_item) |
| 136 if index % 2 == 0: |
| 137 test_thread.AddAsyncSlice(device_item) |
| 138 model.FinalizeImport() |
| 139 |
| 140 metric = gpu_timeline.GPUTimelineMetric() |
| 141 self.assertRaises(AssertionError, self.GetResults, |
| 142 metric, model=model, renderer_thread=test_thread, |
| 143 interaction_records=INTERACTION_RECORDS) |
| 144 |
| 145 def testFewExtraServiceTracesDoesNotAssert(self): |
| 146 """Test a few extra GPU service traces will not cause mismatch assertion.""" |
| 147 model = model_module.TimelineModel() |
| 148 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 149 for index in xrange(4): |
| 150 service_item, device_item = _CreateGPUAsyncSlices('test_item', 100, 10) |
| 151 test_thread.AddAsyncSlice(service_item) |
| 152 if index % 2 == 0: |
| 153 test_thread.AddAsyncSlice(device_item) |
| 154 model.FinalizeImport() |
| 155 |
| 156 metric = gpu_timeline.GPUTimelineMetric() |
| 157 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 158 interaction_records=INTERACTION_RECORDS) |
| 159 |
| 160 self.assertTrue(results) |
| 161 |
| 162 def testFewExtraDeviceTracesDoesAssert(self): |
| 163 """Test a few extra GPU device traces will cause mismatch assertion.""" |
| 164 model = model_module.TimelineModel() |
| 165 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 166 for index in xrange(4): |
| 167 service_item, device_item = _CreateGPUAsyncSlices('test_item', 100, 10) |
| 168 test_thread.AddAsyncSlice(device_item) |
| 169 if index % 2 == 0: |
| 170 test_thread.AddAsyncSlice(service_item) |
| 171 model.FinalizeImport() |
| 172 |
| 173 metric = gpu_timeline.GPUTimelineMetric() |
| 174 self.assertRaises(AssertionError, self.GetResults, |
| 175 metric, model=model, renderer_thread=test_thread, |
| 176 interaction_records=INTERACTION_RECORDS) |
| 177 |
| 178 def testMismatchingServiceDeviceNameAsserts(self): |
| 179 """Test that service/device trace names must match.""" |
| 180 model = model_module.TimelineModel() |
| 181 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 182 service_item, device_item = _CreateGPUAsyncSlices('test_item', 100, 10) |
| 183 device_item.name = 'test_item_2' |
| 184 test_thread.AddAsyncSlice(device_item) |
| 185 test_thread.AddAsyncSlice(service_item) |
| 186 model.FinalizeImport() |
| 187 |
| 188 metric = gpu_timeline.GPUTimelineMetric() |
| 189 self.assertRaises(AssertionError, self.GetResults, |
| 190 metric, model=model, renderer_thread=test_thread, |
| 191 interaction_records=INTERACTION_RECORDS) |
| 192 |
| 193 def testFrameSeparation(self): |
| 194 """Test frames are correctly calculated using the frame end marker.""" |
| 195 model = model_module.TimelineModel() |
| 196 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 197 |
| 198 # First frame is 10 seconds. |
| 199 for slice_item in _CreateGPUAsyncSlices('test_item', 100, 10): |
| 200 test_thread.AddAsyncSlice(slice_item) |
| 201 test_thread.BeginSlice(FRAME_END_CATEGORY, FRAME_END_NAME, 105) |
| 202 test_thread.EndSlice(110) |
| 203 |
| 204 # Second frame is 20 seconds. |
| 205 for slice_item in _CreateGPUAsyncSlices('test_item', 110, 20): |
| 206 test_thread.AddAsyncSlice(slice_item) |
| 207 |
| 208 model.FinalizeImport() |
| 209 |
| 210 metric = gpu_timeline.GPUTimelineMetric() |
| 211 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 212 interaction_records=INTERACTION_RECORDS) |
| 213 |
| 214 results.AssertHasPageSpecificScalarValue( |
| 215 'total_frame_max', 'ms', 20) |
| 216 results.AssertHasPageSpecificScalarValue( |
| 217 'total_frame_avg', 'ms', 15) |
| 218 results.AssertHasPageSpecificScalarValue( |
| 219 'total_frame_stddev', 'ms', 5) |
| 220 |
| 221 def testTrackedNameTraces(self): |
| 222 """Be sure tracked names are being recorded correctly.""" |
| 223 self.assertGreater(len(gpu_timeline.TRACKED_NAMES), 0) |
| 224 |
| 225 marker_name, result_name = gpu_timeline.TRACKED_NAMES.iteritems().next() |
| 226 |
| 227 model = model_module.TimelineModel() |
| 228 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 229 for slice_item in _CreateGPUAsyncSlices(marker_name, 100, 10): |
| 230 test_thread.AddAsyncSlice(slice_item) |
| 231 model.FinalizeImport() |
| 232 |
| 233 metric = gpu_timeline.GPUTimelineMetric() |
| 234 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 235 interaction_records=INTERACTION_RECORDS) |
| 236 |
| 237 results.AssertHasPageSpecificScalarValue( |
| 238 result_name + '_service_max', 'ms', 10) |
| 239 results.AssertHasPageSpecificScalarValue( |
| 240 result_name + '_service_avg', 'ms', 10) |
| 241 results.AssertHasPageSpecificScalarValue( |
| 242 result_name + '_service_stddev', 'ms', 0) |
| 243 |
| 244 def testTrackedNameWithContextIDTraces(self): |
| 245 """Be sure tracked names with context IDs are recorded correctly.""" |
| 246 self.assertGreater(len(gpu_timeline.TRACKED_NAMES), 0) |
| 247 |
| 248 marker_name, result_name = gpu_timeline.TRACKED_NAMES.iteritems().next() |
| 249 context_id = '-0x1234' |
| 250 |
| 251 model = model_module.TimelineModel() |
| 252 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 253 for slice_item in _CreateGPUAsyncSlices(marker_name + context_id, 100, 10): |
| 254 test_thread.AddAsyncSlice(slice_item) |
| 255 model.FinalizeImport() |
| 256 |
| 257 metric = gpu_timeline.GPUTimelineMetric() |
| 258 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 259 interaction_records=INTERACTION_RECORDS) |
| 260 |
| 261 results.AssertHasPageSpecificScalarValue( |
| 262 result_name + '_service_max', 'ms', 10) |
| 263 results.AssertHasPageSpecificScalarValue( |
| 264 result_name + '_service_avg', 'ms', 10) |
| 265 results.AssertHasPageSpecificScalarValue( |
| 266 result_name + '_service_stddev', 'ms', 0) |
| 267 |
| 268 def testOutOfOrderDeviceTraces(self): |
| 269 """Out of order device traces are still matched up to correct services.""" |
| 270 self.assertGreaterEqual(len(gpu_timeline.TRACKED_NAMES), 2) |
| 271 |
| 272 tracked_names_iter = gpu_timeline.TRACKED_NAMES.iteritems() |
| 273 marker1_name, result1_name = tracked_names_iter.next() |
| 274 marker2_name, result2_name = tracked_names_iter.next() |
| 275 |
| 276 model = model_module.TimelineModel() |
| 277 test_thread = model.GetOrCreateProcess(1).GetOrCreateThread(2) |
| 278 |
| 279 # marker1 lasts for 10 seconds. |
| 280 service_item1, device_item1 = _CreateGPUAsyncSlices(marker1_name, 100, 10) |
| 281 # marker2 lasts for 20 seconds. |
| 282 service_item2, device_item2 = _CreateGPUAsyncSlices(marker2_name, 200, 20) |
| 283 |
| 284 # Append out of order |
| 285 test_thread.AddAsyncSlice(service_item1) |
| 286 test_thread.AddAsyncSlice(service_item2) |
| 287 test_thread.AddAsyncSlice(device_item2) |
| 288 test_thread.AddAsyncSlice(device_item1) |
| 289 |
| 290 model.FinalizeImport() |
| 291 |
| 292 metric = gpu_timeline.GPUTimelineMetric() |
| 293 results = self.GetResults(metric, model=model, renderer_thread=test_thread, |
| 294 interaction_records=INTERACTION_RECORDS) |
| 295 |
| 296 results.AssertHasPageSpecificScalarValue( |
| 297 result1_name + '_service_max', 'ms', 10) |
| 298 results.AssertHasPageSpecificScalarValue( |
| 299 result1_name + '_service_avg', 'ms', 10) |
| 300 results.AssertHasPageSpecificScalarValue( |
| 301 result1_name + '_service_stddev', 'ms', 0) |
| 302 results.AssertHasPageSpecificScalarValue( |
| 303 result2_name + '_service_max', 'ms', 20) |
| 304 results.AssertHasPageSpecificScalarValue( |
| 305 result2_name + '_service_avg', 'ms', 20) |
| 306 results.AssertHasPageSpecificScalarValue( |
| 307 result2_name + '_service_stddev', 'ms', 0) |
OLD | NEW |