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