OLD | NEW |
---|---|
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <!-- | 2 <!-- |
3 Copyright 2017 The Chromium Authors. All rights reserved. | 3 Copyright 2017 The Chromium Authors. All rights reserved. |
4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
5 found in the LICENSE file. | 5 found in the LICENSE file. |
6 --> | 6 --> |
7 | 7 |
8 <link rel="import" href="/tracing/core/test_utils.html"> | 8 <link rel="import" href="/tracing/core/test_utils.html"> |
9 <link rel="import" href="/tracing/extras/chrome/cpu_time.html"> | 9 <link rel="import" href="/tracing/extras/chrome/cpu_time.html"> |
10 <link rel="import" href="/tracing/extras/chrome/cpu_time_test_utils.html"> | |
10 | 11 |
11 <script> | 12 <script> |
12 'use strict'; | 13 'use strict'; |
13 | 14 |
14 tr.b.unittest.testSuite(function() { | 15 tr.b.unittest.testSuite(function() { |
15 const getStageToInitiatorToSegmentBounds = | 16 const getStageToInitiatorToSegmentBounds = |
16 tr.e.chrome.cpuTime.getStageToInitiatorToSegmentBounds; | 17 tr.e.chrome.cpuTime.getStageToInitiatorToSegmentBounds; |
17 | 18 |
18 const INITIATOR_TYPE = tr.model.um.INITIATOR_TYPE; | 19 const INITIATOR_TYPE = tr.model.um.INITIATOR_TYPE; |
19 | 20 |
21 const CHROME_PROCESS_NAMES = | |
22 tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES; | |
23 | |
24 const constructMultiDimensionalView = | |
25 tr.e.chrome.cpuTime.constructMultiDimensionalView; | |
26 | |
27 const buildModelFromSpec = tr.e.chrome.cpuTimeTestUtils.buildModelFromSpec; | |
28 | |
20 test('getCpuTimeForThread', () => { | 29 test('getCpuTimeForThread', () => { |
21 const model = tr.c.TestUtils.newModel(function(model) { | 30 const model = tr.c.TestUtils.newModel(function(model) { |
22 const thread = model.getOrCreateProcess(1).getOrCreateThread(1); | 31 const thread = model.getOrCreateProcess(1).getOrCreateThread(1); |
23 const sliceSpecs = [ | 32 const sliceSpecs = [ |
24 {wallTimeBounds: [100, 200], cpuStart: 120, cpuDuration: 50}, | 33 {wallTimeBounds: [100, 200], cpuStart: 120, cpuDuration: 50}, |
25 {wallTimeBounds: [300, 600], cpuStart: 350, cpuDuration: 150} | 34 {wallTimeBounds: [300, 600], cpuStart: 350, cpuDuration: 150} |
26 ]; | 35 ]; |
27 for (const sliceSpec of sliceSpecs) { | 36 for (const sliceSpec of sliceSpecs) { |
28 thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ | 37 thread.sliceGroup.pushSlice(tr.c.TestUtils.newSliceEx({ |
29 type: tr.model.ThreadSlice, | 38 type: tr.model.ThreadSlice, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 const map = getStageToInitiatorToSegmentBounds( | 78 const map = getStageToInitiatorToSegmentBounds( |
70 model.userModel.segments, model.bounds); | 79 model.userModel.segments, model.bounds); |
71 | 80 |
72 // Ignoring Idle Expectations, we have the following segments: | 81 // Ignoring Idle Expectations, we have the following segments: |
73 // [100, 300]: CSS Animation | 82 // [100, 300]: CSS Animation |
74 // [300, 400]: CSS Animation, Video Animation | 83 // [300, 400]: CSS Animation, Video Animation |
75 // [400, 600]: Scroll Response | 84 // [400, 600]: Scroll Response |
76 const allSegments = map.get('all_stages').get('all_initiators'); | 85 const allSegments = map.get('all_stages').get('all_initiators'); |
77 assert.sameDeepMembers( | 86 assert.sameDeepMembers( |
78 allSegments.map(s => [s.min, s.max]), | 87 allSegments.map(s => [s.min, s.max]), |
79 [[100, 300], [300, 400], [400, 600]]); | 88 [[100, 300], [300, 400], [400, 600]] |
89 ); | |
80 | 90 |
81 const videoAnimationSegments = | 91 const videoAnimationSegments = |
82 map.get('Animation').get(INITIATOR_TYPE.VIDEO); | 92 map.get('Animation').get(INITIATOR_TYPE.VIDEO); |
83 assert.sameDeepMembers( | 93 assert.sameDeepMembers( |
84 videoAnimationSegments.map(s => [s.min, s.max]), | 94 videoAnimationSegments.map(s => [s.min, s.max]), |
85 [[300, 400]]); | 95 [[300, 400]]); |
86 | 96 |
87 const cssAnimationSegments = | 97 const cssAnimationSegments = |
88 map.get('Animation').get(INITIATOR_TYPE.CSS); | 98 map.get('Animation').get(INITIATOR_TYPE.CSS); |
89 assert.sameDeepMembers( | 99 assert.sameDeepMembers( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 | 140 |
131 const map = getStageToInitiatorToSegmentBounds(model.userModel.segments, | 141 const map = getStageToInitiatorToSegmentBounds(model.userModel.segments, |
132 tr.b.math.Range.fromExplicitRange(150, 350)); | 142 tr.b.math.Range.fromExplicitRange(150, 350)); |
133 | 143 |
134 // Ignoring Idle Expectations, we have the following segments in range: | 144 // Ignoring Idle Expectations, we have the following segments in range: |
135 // [150, 300]: CSS Animation | 145 // [150, 300]: CSS Animation |
136 // [300, 350]: CSS Animation, Video Animation | 146 // [300, 350]: CSS Animation, Video Animation |
137 const allSegments = map.get('all_stages').get('all_initiators'); | 147 const allSegments = map.get('all_stages').get('all_initiators'); |
138 assert.sameDeepMembers( | 148 assert.sameDeepMembers( |
139 allSegments.map(s => [s.min, s.max]), | 149 allSegments.map(s => [s.min, s.max]), |
140 [[150, 300], [300, 350]]); | 150 [[150, 300], [300, 350]] |
151 ); | |
141 | 152 |
142 const videoAnimationSegments = | 153 const videoAnimationSegments = |
143 map.get('Animation').get(INITIATOR_TYPE.VIDEO); | 154 map.get('Animation').get(INITIATOR_TYPE.VIDEO); |
144 assert.sameDeepMembers( | 155 assert.sameDeepMembers( |
145 videoAnimationSegments.map(s => [s.min, s.max]), | 156 videoAnimationSegments.map(s => [s.min, s.max]), |
146 [[300, 350]]); | 157 [[300, 350]]); |
147 | 158 |
148 const cssAnimationSegments = | 159 const cssAnimationSegments = |
149 map.get('Animation').get(INITIATOR_TYPE.CSS); | 160 map.get('Animation').get(INITIATOR_TYPE.CSS); |
150 assert.sameDeepMembers( | 161 assert.sameDeepMembers( |
151 cssAnimationSegments.map(s => [s.min, s.max]), | 162 cssAnimationSegments.map(s => [s.min, s.max]), |
152 [[150, 300], [300, 350]]); | 163 [[150, 300], [300, 350]]); |
153 | 164 |
154 const allAnimationSegments = | 165 const allAnimationSegments = |
155 map.get('Animation').get('all_initiators'); | 166 map.get('Animation').get('all_initiators'); |
156 assert.sameDeepMembers( | 167 assert.sameDeepMembers( |
157 allAnimationSegments.map(s => [s.min, s.max]), | 168 allAnimationSegments.map(s => [s.min, s.max]), |
158 [[150, 300], [300, 350]]); | 169 [[150, 300], [300, 350]]); |
159 | 170 |
160 // There should be no Response segments | 171 // There should be no Response segments |
161 assert.isFalse(map.has('Response')); | 172 assert.isFalse(map.has('Response')); |
162 }); | 173 }); |
174 | |
175 /** | |
176 * Given the root node of a top down multidimensional tree view, and returns | |
tdresser
2017/04/10 20:48:29
and returns -> returns
dproy
2017/05/11 00:50:46
Done.
| |
177 * the node at |path|. | |
178 */ | |
179 function getNodeValues_(root, path) { | |
180 let node = root; | |
181 for (let i = 0; i <= 2; i++) { | |
tdresser
2017/04/10 20:48:29
Why 2? (Maybe deserves a comment?)
dproy
2017/05/11 00:50:46
Changed to path.length.
| |
182 for (const component of path[i]) { | |
183 node = node.children[i].get(component); | |
184 } | |
185 } | |
186 return node.values; | |
187 } | |
188 | |
189 const getCpuUsage_ = nodeValues => nodeValues[0].total; | |
190 const getCpuTotal_ = nodeValues => nodeValues[1].total; | |
191 | |
192 /** | |
193 * Returns a simple model spec with one process (browser process) and one | |
194 * thread (CrBrowserMain). | |
195 * | |
196 * It does not contain any slices or expectations - those should be added | |
197 * manually. | |
198 * | |
199 * This is a function instead of just a variable because the test functions | |
200 * are meant to modify this modelSpec and insert suitable expectations. | |
201 */ | |
202 function getSimpleModelSpec_() { | |
203 return { | |
204 processes: [ | |
205 { | |
206 name: 'Browser', | |
207 pid: 12345, | |
208 threads: [ | |
209 { | |
210 name: 'CrBrowserMain', | |
211 tid: 1, | |
212 slices: [] | |
213 }, | |
214 ], | |
215 }, | |
216 ], | |
217 expectations: [], | |
218 }; | |
219 } | |
220 | |
221 test('constructMultiDimensionalView_' + | |
222 'slicesDoNotStraddleExpecationBoundaries', () => { | |
223 const simpleModelSpec = getSimpleModelSpec_(); | |
224 simpleModelSpec.processes[0].threads[0].slices.push( | |
225 {range: [150, 200], cpu: 30}, | |
226 {range: [205, 255], cpu: 20} | |
227 ); | |
228 simpleModelSpec.expectations.push( | |
229 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, range: [100, 300]} | |
230 ); | |
231 | |
232 const path = [ | |
233 [CHROME_PROCESS_NAMES.BROWSER], | |
234 ['CrBrowserMain'], ['Animation', 'CSS']]; | |
235 | |
236 const model = buildModelFromSpec(simpleModelSpec); | |
237 const root = constructMultiDimensionalView(model, model.bounds); | |
238 const values = getNodeValues_(root, path); | |
239 | |
240 assert.closeTo(getCpuUsage_(values), (30 + 20) / 200, 1e-7); | |
tdresser
2017/04/10 20:48:29
It might be worth adding comments indicating where
dproy
2017/05/11 00:50:46
I added a few comments about the calculations, esp
| |
241 assert.closeTo(getCpuTotal_(values), (30 + 20), 1e-7); | |
242 }); | |
243 | |
244 test('constructMultiDimensionalView_' + | |
245 'slicesStraddleExpectationBoundaries', () => { | |
246 const simpleModelSpec = getSimpleModelSpec_(); | |
247 simpleModelSpec.processes[0].threads[0].slices.push( | |
248 {range: [150, 200], cpu: 30}, | |
249 {range: [205, 255], cpu: 20} | |
250 ); | |
251 simpleModelSpec.expectations.push( | |
252 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
253 range: [75, 175]} | |
254 ); | |
255 const path = [ | |
256 [CHROME_PROCESS_NAMES.BROWSER], | |
257 ['CrBrowserMain'], ['Animation', 'Video'] | |
258 ]; | |
259 | |
260 const model = buildModelFromSpec(simpleModelSpec); | |
261 const root = constructMultiDimensionalView(model, model.bounds); | |
262 const values = getNodeValues_(root, path); | |
263 | |
264 assert.closeTo(getCpuUsage_(values), 15 / 100, 1e-7); | |
265 assert.closeTo(getCpuTotal_(values), 15, 1e-7); | |
266 }); | |
267 | |
268 test('constructMultiDimensionalView_' + | |
269 'singleThread-disjointExpectationsOfSameInitiator', () => { | |
270 const simpleModelSpec = getSimpleModelSpec_(); | |
271 simpleModelSpec.processes[0].threads[0].slices.push( | |
272 {range: [150, 200], cpu: 30}, | |
273 {range: [205, 255], cpu: 20} | |
274 ); | |
275 simpleModelSpec.expectations.push( | |
276 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
277 range: [100, 160]}, | |
278 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
279 range: [205, 225]} | |
280 ); | |
281 const path = [ | |
282 [CHROME_PROCESS_NAMES.BROWSER], | |
283 ['CrBrowserMain'], ['Response', 'Scroll'] | |
284 ]; | |
285 | |
286 const model = buildModelFromSpec(simpleModelSpec); | |
287 const root = constructMultiDimensionalView(model, model.bounds); | |
288 const values = getNodeValues_(root, path); | |
289 | |
290 assert.closeTo(getCpuUsage_(values), | |
291 (0.2 * 30 + 0.4 * 20) / (60 + 20), 1e-7); | |
292 assert.closeTo(getCpuTotal_(values), | |
293 0.2 * 30 + 0.4 * 20, 1e-7); | |
294 }); | |
295 | |
296 test('constructMultiDimensionalView_' + | |
297 'singleThread-overlappingExpectationsOfSameInitiators', () => { | |
298 const simpleModelSpec = getSimpleModelSpec_(); | |
299 simpleModelSpec.processes[0].threads[0].slices.push( | |
300 {range: [150, 200], cpu: 30}, | |
301 {range: [205, 255], cpu: 20} | |
302 ); | |
303 simpleModelSpec.expectations.push( | |
304 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
305 range: [100, 190]}, | |
306 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
307 range: [160, 230]} | |
308 ); | |
309 const path = [ | |
310 [CHROME_PROCESS_NAMES.BROWSER], | |
311 ['CrBrowserMain'], ['Animation', 'CSS'] | |
312 ]; | |
313 | |
314 const model = buildModelFromSpec(simpleModelSpec); | |
315 const root = constructMultiDimensionalView(model, model.bounds); | |
316 const values = getNodeValues_(root, path); | |
317 | |
318 assert.closeTo(getCpuUsage_(values), (30 + 0.5 * 20) / 130, 1e-7); | |
319 assert.closeTo(getCpuTotal_(values), 30 + 0.5 * 20, 1e-7); | |
320 }); | |
321 | |
322 test('constructMultiDimensionalView_' + | |
323 'singleThread-overlappingExpectationsOfDifferentInitiators', () => { | |
324 const simpleModelSpec = getSimpleModelSpec_(); | |
325 simpleModelSpec.processes[0].threads[0].slices.push( | |
326 {range: [150, 200], cpu: 30}, | |
327 {range: [205, 255], cpu: 20} | |
328 ); | |
329 simpleModelSpec.expectations.push( | |
330 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
331 range: [100, 190]}, | |
332 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
333 range: [160, 230]} | |
334 ); | |
335 const path = [ | |
336 [CHROME_PROCESS_NAMES.BROWSER], | |
337 ['CrBrowserMain'], ['Animation', 'all_initiators'] | |
338 ]; | |
339 | |
340 const model = buildModelFromSpec(simpleModelSpec); | |
341 const root = constructMultiDimensionalView(model, model.bounds); | |
342 const values = getNodeValues_(root, path); | |
343 | |
344 assert.closeTo(getCpuUsage_(values), | |
345 (30 + 0.5 * 20) / 130, 1e-7); | |
346 assert.closeTo(getCpuTotal_(values), | |
347 30 + 0.5 * 20, 1e-7); | |
348 }); | |
349 | |
350 test('constructMultiDimensionalView_' + | |
351 'singleThread-allStages-customRangeOfInterest', () => { | |
352 const simpleModelSpec = getSimpleModelSpec_(); | |
353 simpleModelSpec.processes[0].threads[0].slices.push( | |
354 {range: [150, 200], cpu: 30}, | |
355 {range: [205, 255], cpu: 20} | |
356 ); | |
357 simpleModelSpec.expectations.push( | |
358 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
359 range: [100, 190]}, | |
360 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
361 range: [160, 230]} | |
362 ); | |
363 const path = [ | |
364 [CHROME_PROCESS_NAMES.BROWSER], | |
365 ['CrBrowserMain'], ['all_stages', 'all_initiators'] | |
366 ]; | |
367 | |
368 const model = buildModelFromSpec(simpleModelSpec); | |
369 const rangeOfInterest = new tr.b.math.Range.fromExplicitRange(100, 210); | |
370 const root = constructMultiDimensionalView(model, rangeOfInterest); | |
371 const values = getNodeValues_(root, path); | |
372 | |
373 assert.closeTo(getCpuUsage_(values), (30 + 0.1 * 20) / 110, 1e-7); | |
374 assert.closeTo(getCpuTotal_(values), 30 + 0.1 * 20, 1e-7); | |
375 }); | |
376 | |
377 /** | |
378 * Returns a model spec where the browser process has two worker threads. | |
379 * | |
380 * This is a function instead of just a variable because the test functions | |
381 * are meant to modify this modelSpec and insert suitable expectations. | |
382 */ | |
383 function getMultipleThreadsOfSameTypeModelSpec_() { | |
384 return { | |
385 processes: [ | |
386 { | |
387 name: 'Browser', | |
388 pid: 12345, | |
389 threads: [ | |
390 { | |
391 name: 'CrBrowserMain', | |
392 tid: 1, | |
393 slices: [], | |
394 }, | |
395 { | |
396 name: 'Worker/1', | |
397 tid: 42, | |
398 slices: (() => { | |
399 const slices = []; | |
400 for (let i = 0; i < 1000; i += 20) { | |
401 slices.push({range: [i, i + 10], cpu: 5}); | |
402 } | |
403 return slices; | |
404 })(), | |
405 }, | |
406 { | |
407 name: 'Worker/2', | |
408 tid: 52, | |
409 slices: (() => { | |
410 const slices = []; | |
411 for (let i = 0; i < 1000; i += 100) { | |
412 slices.push({range: [i, i + 80], cpu: 40}); | |
413 } | |
414 return slices; | |
415 })(), | |
416 }, | |
417 ], | |
418 }, | |
419 ], | |
420 | |
421 expectations: [], | |
422 }; | |
423 } | |
424 | |
425 test('constructMultiDimensionalView_multipleThreadsOfSameType_' + | |
426 'singleExpectation', () => { | |
427 const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); | |
428 modelSpec.expectations.push( | |
429 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
430 range: [0, 90]} | |
431 ); | |
432 | |
433 const path = [ | |
434 [CHROME_PROCESS_NAMES.BROWSER], | |
435 ['Worker'], ['Animation', 'Video'] | |
436 ]; | |
437 | |
438 const model = buildModelFromSpec(modelSpec); | |
439 const root = constructMultiDimensionalView(model, model.bounds); | |
440 const values = getNodeValues_(root, path); | |
441 | |
442 assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 90, 1e-7); | |
443 assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7); | |
444 }); | |
445 | |
446 test('constructMultiDimensionalView_multipleThreadsOfSameType_' + | |
447 'disjointExpectationSameInitiator', () => { | |
448 const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); | |
449 modelSpec.expectations.push( | |
450 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
451 range: [500, 560]}, | |
452 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
453 range: [690, 890]} | |
454 ); | |
455 | |
456 const path = [ | |
457 [CHROME_PROCESS_NAMES.BROWSER], | |
458 ['Worker'], ['Animation', 'CSS'] | |
459 ]; | |
460 | |
461 const model = buildModelFromSpec(modelSpec); | |
462 const root = constructMultiDimensionalView(model, model.bounds); | |
463 const values = getNodeValues_(root, path); | |
464 | |
465 assert.closeTo(getCpuUsage_(values), | |
466 ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)) / (60 + 200), 1e-7); | |
467 assert.closeTo(getCpuTotal_(values), | |
468 (5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2), 1e-7); | |
469 }); | |
470 | |
471 test('constructMultiDimensionalView_multipleThreadsOfSameType_' + | |
472 'overlappingExpectationsOfSameInitiator', () => { | |
473 const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); | |
474 // [Scroll R] | |
475 // [Scroll R] | |
476 modelSpec.expectations.push( | |
477 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
478 range: [210, 260]}, | |
479 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
480 range: [250, 300]} | |
481 ); | |
482 | |
483 const path = [ | |
484 [CHROME_PROCESS_NAMES.BROWSER], | |
485 ['Worker'], ['Response', 'Scroll'] | |
486 ]; | |
487 | |
488 const model = buildModelFromSpec(modelSpec); | |
489 const root = constructMultiDimensionalView(model, model.bounds); | |
490 const values = getNodeValues_(root, path); | |
491 | |
492 assert.closeTo(getCpuUsage_(values), | |
493 (5 * 4 + 40 * (70 / 80)) / 90, 1e-7); | |
494 assert.closeTo(getCpuTotal_(values), | |
495 5 * 4 + 40 * (70 / 80), 1e-7); | |
496 }); | |
497 | |
498 test('constructMultiDimensionalView_multipleThreadsOfSameType_' + | |
499 'disjointExpectationsAllInitiators', () => { | |
500 const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); | |
501 modelSpec.expectations.push( | |
502 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
503 range: [0, 90]}, | |
504 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
505 range: [500, 560]}, | |
506 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
507 range: [690, 890]} | |
508 ); | |
509 | |
510 const path = [ | |
511 [CHROME_PROCESS_NAMES.BROWSER], | |
512 ['Worker'], ['Animation', 'all_initiators'] | |
513 ]; | |
514 | |
515 const model = buildModelFromSpec(modelSpec); | |
516 const root = constructMultiDimensionalView(model, model.bounds); | |
517 const values = getNodeValues_(root, path); | |
518 | |
519 assert.closeTo(getCpuUsage_(values), | |
520 ((5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2))) / | |
521 (90 + 60 + 200), 1e-7); | |
522 assert.closeTo(getCpuTotal_(values), | |
523 (5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)), | |
524 1e-7); | |
525 }); | |
526 | |
527 | |
528 test('constructMultiDimensionalView_multipleThreadsOfSameType_' + | |
529 'overlappingExpectationsAllInitiators', () => { | |
530 const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); | |
531 // [Click R] | |
532 // [Scroll R] | |
533 // [Scroll R] | |
534 modelSpec.expectations.push( | |
535 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
536 range: [200, 220]}, | |
537 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
538 range: [210, 260]}, | |
539 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
540 range: [250, 300]} | |
541 ); | |
542 | |
543 const path = [ | |
544 [CHROME_PROCESS_NAMES.BROWSER], | |
545 ['Worker'], ['Response', 'all_initiators'] | |
546 ]; | |
547 | |
548 const model = buildModelFromSpec(modelSpec); | |
549 const root = constructMultiDimensionalView(model, model.bounds); | |
550 const values = getNodeValues_(root, path); | |
551 | |
552 assert.closeTo(getCpuUsage_(values), | |
553 (5 * 5 + 40) / 100, 1e-7); | |
554 assert.closeTo(getCpuTotal_(values), | |
555 5 * 5 + 40, 1e-7); | |
556 }); | |
557 | |
558 | |
559 test('constructMultiDimensionalView_multipleThreadsOfSameType_' + | |
560 'allStagesAllInitiators', () => { | |
561 const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); | |
562 // [Video A] [Click R] [CSS A] [ CSS A ] | |
563 // [Scroll R] | |
564 // [Scroll R] | |
565 modelSpec.expectations.push( | |
566 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
567 range: [0, 90]}, | |
568 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
569 range: [200, 220]}, | |
570 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
571 range: [210, 260]}, | |
572 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
573 range: [250, 300]}, | |
574 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
575 range: [500, 560]}, | |
576 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
577 range: [690, 890]} | |
578 ); | |
579 | |
580 const path = [ | |
581 [CHROME_PROCESS_NAMES.BROWSER], | |
582 ['Worker'], ['all_stages', 'all_initiators'] | |
583 ]; | |
584 | |
585 const model = buildModelFromSpec(modelSpec); | |
586 const root = constructMultiDimensionalView(model, model.bounds); | |
587 const values = getNodeValues_(root, path); | |
588 | |
589 assert.closeTo(getCpuUsage_(values), (250 + 400) / 990, 1e-7); | |
590 assert.closeTo(getCpuTotal_(values), 250 + 400, 1e-7); | |
591 }); | |
592 | |
593 /** | |
594 * Returns a model spec where there are two renderer processes, each with a | |
595 * renderer main thread. | |
596 * | |
597 * This is a function instead of just a variable because the test functions | |
598 * are meant to modify this modelSpec and insert suitable expectations. | |
599 */ | |
600 function getMultipleProcessesOfSameTypeModelSpec_() { | |
601 return { | |
602 processes: [ | |
603 { | |
604 name: 'Browser', | |
605 pid: 12345, | |
606 threads: [ | |
607 { | |
608 name: 'CrBrowserMain', | |
609 tid: 1, | |
610 slices: [], | |
611 }, | |
612 ], | |
613 }, | |
614 { | |
615 name: 'Renderer', | |
616 pid: 20001, | |
617 threads: [ | |
618 { | |
619 name: 'CrRendererMain', | |
620 tid: 42, | |
621 slices: (() => { | |
622 const slices = []; | |
623 for (let i = 0; i < 1000; i += 20) { | |
624 slices.push({range: [i, i + 10], cpu: 5}); | |
625 } | |
626 return slices; | |
627 })(), | |
628 }, | |
629 ], | |
630 }, | |
631 { | |
632 name: 'Renderer', | |
633 pid: 30001, | |
634 threads: [ | |
635 { | |
636 name: 'CrRendererMain', | |
637 tid: 52, | |
638 slices: (() => { | |
639 const slices = []; | |
640 for (let i = 0; i < 1000; i += 100) { | |
641 slices.push({range: [i, i + 80], cpu: 40}); | |
642 } | |
643 return slices; | |
644 })(), | |
645 }, | |
646 ] | |
647 }, | |
648 ], | |
649 | |
650 expectations: [], | |
651 }; | |
652 } | |
653 | |
654 test('constructMultiDimensionalView_multipleProcessesOfSameType_' + | |
655 'singleExpectation', () => { | |
656 const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); | |
657 modelSpec.expectations.push( | |
658 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
659 range: [0, 90]} | |
660 ); | |
661 | |
662 const path = [ | |
663 [CHROME_PROCESS_NAMES.RENDERER], | |
664 ['CrRendererMain'], ['Animation', 'Video'] | |
665 ]; | |
666 | |
667 const model = buildModelFromSpec(modelSpec); | |
668 const root = constructMultiDimensionalView(model, model.bounds); | |
669 const values = getNodeValues_(root, path); | |
670 | |
671 assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 90, 1e-7); | |
672 assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7); | |
673 }); | |
674 | |
675 test('constructMultiDimensionalView_multipleProcessesOfSameType_' + | |
676 'disjointExpectationSameInitiator', () => { | |
677 const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); | |
678 modelSpec.expectations.push( | |
679 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
680 range: [500, 560]}, | |
681 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
682 range: [690, 890]} | |
683 ); | |
684 | |
685 const path = [ | |
686 [CHROME_PROCESS_NAMES.RENDERER], | |
687 ['CrRendererMain'], ['Animation', 'CSS'] | |
688 ]; | |
689 | |
690 const model = buildModelFromSpec(modelSpec); | |
691 const root = constructMultiDimensionalView(model, model.bounds); | |
692 const values = getNodeValues_(root, path); | |
693 | |
694 assert.closeTo(getCpuUsage_(values), | |
695 ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)) / (60 + 200), 1e-7); | |
696 assert.closeTo(getCpuTotal_(values), | |
697 (5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2), 1e-7); | |
698 }); | |
699 | |
700 test('constructMultiDimensionalView_multipleProcessesOfSameType_' + | |
701 'overlappingExpectationsOfSameInitiator', () => { | |
702 const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); | |
703 // [Scroll R] | |
704 // [Scroll R] | |
705 modelSpec.expectations.push( | |
706 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
707 range: [210, 260]}, | |
708 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
709 range: [250, 300]} | |
710 ); | |
711 | |
712 const path = [ | |
713 [CHROME_PROCESS_NAMES.RENDERER], | |
714 ['CrRendererMain'], ['Response', 'Scroll'] | |
715 ]; | |
716 | |
717 const model = buildModelFromSpec(modelSpec); | |
718 const root = constructMultiDimensionalView(model, model.bounds); | |
719 const values = getNodeValues_(root, path); | |
720 | |
721 assert.closeTo(getCpuUsage_(values), | |
722 (5 * 4 + 40 * (70 / 80)) / 90, 1e-7); | |
723 assert.closeTo(getCpuTotal_(values), | |
724 5 * 4 + 40 * (70 / 80), 1e-7); | |
725 }); | |
726 | |
727 test('constructMultiDimensionalView_multipleProcessesOfSameType_' + | |
728 'disjointExpectationsAllInitiators', () => { | |
729 const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); | |
730 modelSpec.expectations.push( | |
731 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
732 range: [0, 90]}, | |
733 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
734 range: [500, 560]}, | |
735 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
736 range: [690, 890]} | |
737 ); | |
738 | |
739 const path = [ | |
740 [CHROME_PROCESS_NAMES.RENDERER], | |
741 ['CrRendererMain'], ['Animation', 'all_initiators'] | |
742 ]; | |
743 | |
744 const model = buildModelFromSpec(modelSpec); | |
745 const root = constructMultiDimensionalView(model, model.bounds); | |
746 const values = getNodeValues_(root, path); | |
747 | |
748 assert.closeTo(getCpuUsage_(values), | |
749 ((5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2))) / | |
750 (90 + 60 + 200), 1e-7); | |
751 assert.closeTo(getCpuTotal_(values), | |
752 (5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)), | |
753 1e-7); | |
754 }); | |
755 | |
756 | |
757 test('constructMultiDimensionalView_multipleProcessesOfSameType_' + | |
758 'overlappingExpectationsAllInitiators', () => { | |
759 const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); | |
760 // [Click R] | |
761 // [Scroll R] | |
762 // [Scroll R] | |
763 modelSpec.expectations.push( | |
764 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
765 range: [200, 220]}, | |
766 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
767 range: [210, 260]}, | |
768 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
769 range: [250, 300]} | |
770 ); | |
771 | |
772 const path = [ | |
773 [CHROME_PROCESS_NAMES.RENDERER], | |
774 ['CrRendererMain'], ['Response', 'all_initiators'] | |
775 ]; | |
776 | |
777 const model = buildModelFromSpec(modelSpec); | |
778 const root = constructMultiDimensionalView(model, model.bounds); | |
779 const values = getNodeValues_(root, path); | |
780 | |
781 assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 100, 1e-7); | |
782 assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7); | |
783 }); | |
784 | |
785 | |
786 test('constructMultiDimensionalView_multipleProcessesOfSameType_' + | |
787 'allStagesAllInitiators', () => { | |
788 const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); | |
789 // [Video A] [Click R] [CSS A] [ CSS A ] | |
790 // [Scroll R] | |
791 // [Scroll R] | |
792 modelSpec.expectations.push( | |
793 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
794 range: [0, 90]}, | |
795 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
796 range: [200, 220]}, | |
797 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
798 range: [210, 260]}, | |
799 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
800 range: [250, 300]}, | |
801 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
802 range: [500, 560]}, | |
803 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
804 range: [690, 890]} | |
805 ); | |
806 | |
807 const path = [ | |
808 [CHROME_PROCESS_NAMES.RENDERER], | |
809 ['CrRendererMain'], ['all_stages', 'all_initiators'] | |
810 ]; | |
811 | |
812 const model = buildModelFromSpec(modelSpec); | |
813 const root = constructMultiDimensionalView(model, model.bounds); | |
814 const values = getNodeValues_(root, path); | |
815 | |
816 assert.closeTo(getCpuUsage_(values), (250 + 400) / 990, 1e-7); | |
817 assert.closeTo(getCpuTotal_(values), 250 + 400, 1e-7); | |
818 }); | |
819 | |
820 /** | |
821 * Returns a model spec where the browser process has a main thread and an IO | |
822 * thread. | |
823 * | |
824 * This is a function instead of just a variable because the test functions | |
825 * are meant to modify this modelSpec and insert suitable expectations. | |
826 */ | |
827 function getAllThreadsOfSameProcessModelSpec_() { | |
828 return { | |
829 processes: [ | |
830 { | |
831 name: 'Browser', | |
832 pid: 12345, | |
833 threads: [ | |
834 { | |
835 name: 'CrBrowserMain', | |
836 tid: 1, | |
837 slices: (() => { | |
838 const slices = []; | |
839 for (let i = 0; i < 1000; i += 20) { | |
840 slices.push({range: [i, i + 10], cpu: 5}); | |
841 } | |
842 return slices; | |
843 })(), | |
844 }, | |
845 { | |
846 name: 'Chrome_IOThread', | |
847 tid: 5, | |
848 slices: (() => { | |
849 const slices = []; | |
850 for (let i = 0; i < 1000; i += 100) { | |
851 slices.push({range: [i, i + 80], cpu: 40}); | |
852 } | |
853 return slices; | |
854 })(), | |
855 } | |
856 ], | |
857 }, | |
858 ], | |
859 | |
860 expectations: [], | |
861 }; | |
862 } | |
863 | |
864 | |
865 test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + | |
866 'singleExpectation', () => { | |
867 const modelSpec = getAllThreadsOfSameProcessModelSpec_(); | |
868 modelSpec.expectations.push( | |
869 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
870 range: [0, 90]} | |
871 ); | |
872 | |
873 const pathForAllThreads = [ | |
874 [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'Video']]; | |
875 | |
876 const pathForThread1 = [ | |
877 [CHROME_PROCESS_NAMES.BROWSER], | |
878 ['CrBrowserMain'], ['Animation', 'Video']]; | |
879 | |
880 const pathForThread2 = [ | |
881 [CHROME_PROCESS_NAMES.BROWSER], | |
882 ['Chrome_IOThread'], ['Animation', 'Video']]; | |
883 | |
884 const model = buildModelFromSpec(modelSpec); | |
885 const root = constructMultiDimensionalView(model, model.bounds); | |
886 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
887 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
888 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
889 | |
890 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
891 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
892 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
893 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
894 }); | |
895 | |
896 test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + | |
897 'disjointExpectationSameInitiator', () => { | |
898 const modelSpec = getAllThreadsOfSameProcessModelSpec_(); | |
899 modelSpec.expectations.push( | |
900 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
901 range: [500, 560]}, | |
902 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
903 range: [690, 890]} | |
904 ); | |
905 | |
906 const pathForAllThreads = [ | |
907 [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'CSS']]; | |
908 | |
909 const pathForThread1 = [ | |
910 [CHROME_PROCESS_NAMES.BROWSER], | |
911 ['CrBrowserMain'], ['Animation', 'CSS']]; | |
912 | |
913 const pathForThread2 = [ | |
914 [CHROME_PROCESS_NAMES.BROWSER], | |
915 ['Chrome_IOThread'], ['Animation', 'CSS']]; | |
916 | |
917 const model = buildModelFromSpec(modelSpec); | |
918 const root = constructMultiDimensionalView(model, model.bounds); | |
919 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
920 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
921 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
922 | |
923 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
924 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
925 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
926 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
927 }); | |
928 | |
929 test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + | |
930 'overlappingExpectationsOfSameInitiator', () => { | |
931 const modelSpec = getAllThreadsOfSameProcessModelSpec_(); | |
932 // [Scroll R] | |
933 // [Scroll R] | |
934 modelSpec.expectations.push( | |
935 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
936 range: [210, 260]}, | |
937 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
938 range: [250, 300]} | |
939 ); | |
940 | |
941 const pathForAllThreads = [ | |
942 [CHROME_PROCESS_NAMES.BROWSER], [], ['Response', 'Scroll']]; | |
943 | |
944 const pathForThread1 = [ | |
945 [CHROME_PROCESS_NAMES.BROWSER], | |
946 ['CrBrowserMain'], ['Response', 'Scroll']]; | |
947 | |
948 const pathForThread2 = [ | |
949 [CHROME_PROCESS_NAMES.BROWSER], | |
950 ['Chrome_IOThread'], ['Response', 'Scroll']]; | |
951 | |
952 const model = buildModelFromSpec(modelSpec); | |
953 const root = constructMultiDimensionalView(model, model.bounds); | |
954 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
955 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
956 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
957 | |
958 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
959 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
960 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
961 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
962 }); | |
963 | |
964 test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + | |
965 'disjointExpectationsAllInitiators', () => { | |
966 const modelSpec = getAllThreadsOfSameProcessModelSpec_(); | |
967 modelSpec.expectations.push( | |
968 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
969 range: [0, 90]}, | |
970 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
971 range: [500, 560]}, | |
972 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
973 range: [690, 890]} | |
974 ); | |
975 | |
976 const pathForAllThreads = [ | |
977 [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'all_initiators']]; | |
978 | |
979 const pathForThread1 = [ | |
980 [CHROME_PROCESS_NAMES.BROWSER], | |
981 ['CrBrowserMain'], ['Animation', 'all_initiators']]; | |
982 | |
983 const pathForThread2 = [ | |
984 [CHROME_PROCESS_NAMES.BROWSER], | |
985 ['Chrome_IOThread'], ['Animation', 'all_initiators']]; | |
986 | |
987 const model = buildModelFromSpec(modelSpec); | |
988 const root = constructMultiDimensionalView(model, model.bounds); | |
989 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
990 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
991 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
992 | |
993 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
994 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
995 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
996 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
997 }); | |
998 | |
999 test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + | |
1000 'overlappingExpectationsAllInitiators', () => { | |
1001 const modelSpec = getAllThreadsOfSameProcessModelSpec_(); | |
1002 // [Click R] | |
1003 // [Scroll R] | |
1004 // [Scroll R] | |
1005 modelSpec.expectations.push( | |
1006 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
1007 range: [200, 220]}, | |
1008 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1009 range: [210, 260]}, | |
1010 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1011 range: [250, 300]} | |
1012 ); | |
1013 | |
1014 const pathForAllThreads = [ | |
1015 [CHROME_PROCESS_NAMES.BROWSER], [], ['Response', 'all_initiators']]; | |
1016 | |
1017 const pathForThread1 = [ | |
1018 [CHROME_PROCESS_NAMES.BROWSER], | |
1019 ['CrBrowserMain'], ['Response', 'all_initiators']]; | |
1020 | |
1021 const pathForThread2 = [ | |
1022 [CHROME_PROCESS_NAMES.BROWSER], | |
1023 ['Chrome_IOThread'], ['Response', 'all_initiators']]; | |
1024 | |
1025 const model = buildModelFromSpec(modelSpec); | |
1026 const root = constructMultiDimensionalView(model, model.bounds); | |
1027 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1028 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1029 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1030 | |
1031 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1032 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1033 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1034 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1035 }); | |
1036 | |
1037 test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + | |
1038 'allStagesAllInitiators', () => { | |
1039 const modelSpec = getAllThreadsOfSameProcessModelSpec_(); | |
1040 // [Video A] [Click R] [CSS A] [ CSS A ] | |
1041 // [Scroll R] | |
1042 // [Scroll R] | |
1043 modelSpec.expectations.push( | |
1044 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
1045 range: [0, 90]}, | |
1046 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
1047 range: [200, 220]}, | |
1048 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1049 range: [210, 260]}, | |
1050 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1051 range: [250, 300]}, | |
1052 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1053 range: [500, 560]}, | |
1054 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1055 range: [690, 890]} | |
1056 ); | |
1057 | |
1058 const pathForAllThreads = [ | |
1059 [CHROME_PROCESS_NAMES.BROWSER], [], ['all_stages', 'all_initiators']]; | |
1060 | |
1061 const pathForThread1 = [ | |
1062 [CHROME_PROCESS_NAMES.BROWSER], | |
1063 ['CrBrowserMain'], ['all_stages', 'all_initiators']]; | |
1064 | |
1065 const pathForThread2 = [ | |
1066 [CHROME_PROCESS_NAMES.BROWSER], | |
1067 ['Chrome_IOThread'], ['all_stages', 'all_initiators']]; | |
1068 | |
1069 const model = buildModelFromSpec(modelSpec); | |
1070 const root = constructMultiDimensionalView(model, model.bounds); | |
1071 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1072 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1073 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1074 | |
1075 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1076 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1077 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1078 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1079 }); | |
1080 | |
1081 /** | |
1082 * Returns a model spec where a renderer process and a GPU process both have a | |
1083 * Chrome_ChildIOThread. | |
1084 * | |
1085 * This is a function instead of just a variable because the test functions | |
1086 * are meant to modify this modelSpec and insert suitable expectations. | |
1087 * | |
1088 * The modelSpec includes a basic browser process because it not a valid | |
1089 * chrome model otherwise. | |
1090 */ | |
1091 function getAllProcessesOfSameThreadModelSpec_() { | |
1092 return { | |
1093 processes: [ | |
1094 { | |
1095 name: 'Browser', | |
1096 pid: 12345, | |
1097 threads: [ | |
1098 { | |
1099 name: 'CrBrowserMain', | |
1100 tid: 1, | |
1101 slices: [], | |
1102 }, | |
1103 ], | |
1104 }, | |
1105 { | |
1106 name: 'Renderer', | |
1107 pid: 20001, | |
1108 threads: [ | |
1109 { | |
1110 name: 'Chrome_ChildIOThread', | |
1111 tid: 42, | |
1112 slices: (() => { | |
1113 const slices = []; | |
1114 for (let i = 0; i < 1000; i += 20) { | |
1115 slices.push({range: [i, i + 10], cpu: 5}); | |
1116 } | |
1117 return slices; | |
1118 })(), | |
1119 }, | |
1120 ], | |
1121 }, | |
1122 { | |
1123 name: 'GPU Process', | |
1124 pid: 30001, | |
1125 threads: [ | |
1126 { | |
1127 name: 'Chrome_ChildIOThread', | |
1128 tid: 52, | |
1129 slices: (() => { | |
1130 const slices = []; | |
1131 for (let i = 0; i < 1000; i += 100) { | |
1132 slices.push({range: [i, i + 80], cpu: 40}); | |
1133 } | |
1134 return slices; | |
1135 })(), | |
1136 }, | |
1137 ] | |
1138 }, | |
1139 ], | |
1140 expectations: [], | |
1141 }; | |
1142 } | |
1143 | |
1144 test('constructMultiDimensionalView_AllProcessesOfSameThread_' + | |
1145 'singleExpectation', () => { | |
1146 const modelSpec = getAllProcessesOfSameThreadModelSpec_(); | |
1147 modelSpec.expectations.push( | |
1148 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
1149 range: [0, 90]} | |
1150 ); | |
1151 | |
1152 const pathForAllThreads = [ | |
1153 [], ['Chrome_ChildIOThread'], ['Animation', 'Video']]; | |
1154 | |
1155 const pathForThread1 = [ | |
1156 [CHROME_PROCESS_NAMES.RENDERER], | |
1157 ['Chrome_ChildIOThread'], ['Animation', 'Video']]; | |
1158 | |
1159 const pathForThread2 = [ | |
1160 [CHROME_PROCESS_NAMES.GPU], | |
1161 ['Chrome_ChildIOThread'], ['Animation', 'Video']]; | |
1162 | |
1163 const model = buildModelFromSpec(modelSpec); | |
1164 const root = constructMultiDimensionalView(model, model.bounds); | |
1165 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1166 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1167 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1168 | |
1169 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1170 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1171 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1172 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1173 }); | |
1174 | |
1175 test('constructMultiDimensionalView_AllProcessesOfSameThread_' + | |
1176 'disjointExpectationSameInitiator', () => { | |
1177 const modelSpec = getAllProcessesOfSameThreadModelSpec_(); | |
1178 modelSpec.expectations.push( | |
1179 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1180 range: [500, 560]}, | |
1181 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1182 range: [690, 890]} | |
1183 ); | |
1184 | |
1185 const pathForAllThreads = [ | |
1186 [], ['Chrome_ChildIOThread'], ['Animation', 'CSS']]; | |
1187 | |
1188 const pathForThread1 = [ | |
1189 [CHROME_PROCESS_NAMES.RENDERER], | |
1190 ['Chrome_ChildIOThread'], ['Animation', 'CSS']]; | |
1191 | |
1192 const pathForThread2 = [ | |
1193 [CHROME_PROCESS_NAMES.GPU], | |
1194 ['Chrome_ChildIOThread'], ['Animation', 'CSS']]; | |
1195 | |
1196 const model = buildModelFromSpec(modelSpec); | |
1197 const root = constructMultiDimensionalView(model, model.bounds); | |
1198 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1199 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1200 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1201 | |
1202 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1203 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1204 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1205 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1206 }); | |
1207 | |
1208 test('constructMultiDimensionalView_AllProcessesOfSameThread_' + | |
1209 'overlappingExpectationsOfSameInitiator', () => { | |
1210 const modelSpec = getAllProcessesOfSameThreadModelSpec_(); | |
1211 // [Scroll R] | |
1212 // [Scroll R] | |
1213 modelSpec.expectations.push( | |
1214 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1215 range: [210, 260]}, | |
1216 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1217 range: [250, 300]} | |
1218 ); | |
1219 | |
1220 const pathForAllThreads = [ | |
1221 [], ['Chrome_ChildIOThread'], ['Response', 'Scroll']]; | |
1222 | |
1223 const pathForThread1 = [ | |
1224 [CHROME_PROCESS_NAMES.RENDERER], | |
1225 ['Chrome_ChildIOThread'], ['Response', 'Scroll']]; | |
1226 | |
1227 const pathForThread2 = [ | |
1228 [CHROME_PROCESS_NAMES.GPU], | |
1229 ['Chrome_ChildIOThread'], ['Response', 'Scroll']]; | |
1230 | |
1231 const model = buildModelFromSpec(modelSpec); | |
1232 const root = constructMultiDimensionalView(model, model.bounds); | |
1233 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1234 | |
1235 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1236 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1237 | |
1238 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1239 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1240 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1241 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1242 }); | |
1243 | |
1244 test('constructMultiDimensionalView_AllProcessesOfSameThread_' + | |
1245 'disjointExpectationsAllInitiators', () => { | |
1246 const modelSpec = getAllProcessesOfSameThreadModelSpec_(); | |
1247 modelSpec.expectations.push( | |
1248 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
1249 range: [0, 90]}, | |
1250 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1251 range: [500, 560]}, | |
1252 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1253 range: [690, 890]} | |
1254 ); | |
1255 | |
1256 const pathForAllThreads = [ | |
1257 [], ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']]; | |
1258 | |
1259 const pathForThread1 = [ | |
1260 [CHROME_PROCESS_NAMES.RENDERER], | |
1261 ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']]; | |
1262 | |
1263 const pathForThread2 = [ | |
1264 [CHROME_PROCESS_NAMES.GPU], | |
1265 ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']]; | |
1266 | |
1267 const model = buildModelFromSpec(modelSpec); | |
1268 const root = constructMultiDimensionalView(model, model.bounds); | |
1269 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1270 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1271 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1272 | |
1273 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1274 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1275 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1276 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1277 }); | |
1278 | |
1279 test('constructMultiDimensionalView_AllProcessesOfSameThread_' + | |
1280 'overlappingExpectationsAllInitiators', () => { | |
1281 const modelSpec = getAllProcessesOfSameThreadModelSpec_(); | |
1282 // [Click R] | |
1283 // [Scroll R] | |
1284 // [Scroll R] | |
1285 modelSpec.expectations.push( | |
1286 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
1287 range: [200, 220]}, | |
1288 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1289 range: [210, 260]}, | |
1290 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1291 range: [250, 300]} | |
1292 ); | |
1293 | |
1294 const pathForAllThreads = [ | |
1295 [], ['Chrome_ChildIOThread'], ['Response', 'all_initiators']]; | |
1296 | |
1297 const pathForThread1 = [ | |
1298 [CHROME_PROCESS_NAMES.RENDERER], | |
1299 ['Chrome_ChildIOThread'], ['Response', 'all_initiators']]; | |
1300 | |
1301 const pathForThread2 = [ | |
1302 [CHROME_PROCESS_NAMES.GPU], | |
1303 ['Chrome_ChildIOThread'], ['Response', 'all_initiators']]; | |
1304 | |
1305 const model = buildModelFromSpec(modelSpec); | |
1306 const root = constructMultiDimensionalView(model, model.bounds); | |
1307 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1308 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1309 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1310 | |
1311 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1312 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1313 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1314 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1315 }); | |
1316 | |
1317 test('constructMultiDimensionalView_AllProcessesOfSameThread_' + | |
1318 'allStagesAllInitiators', () => { | |
1319 const modelSpec = getAllProcessesOfSameThreadModelSpec_(); | |
1320 // [Video A] [Click R] [CSS A] [ CSS A ] | |
1321 // [Scroll R] | |
1322 // [Scroll R] | |
1323 modelSpec.expectations.push( | |
1324 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
1325 range: [0, 90]}, | |
1326 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
1327 range: [200, 220]}, | |
1328 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1329 range: [210, 260]}, | |
1330 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1331 range: [250, 300]}, | |
1332 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1333 range: [500, 560]}, | |
1334 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1335 range: [690, 890]} | |
1336 ); | |
1337 | |
1338 const pathForAllThreads = [ | |
1339 [], ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']]; | |
1340 | |
1341 const pathForThread1 = [ | |
1342 [CHROME_PROCESS_NAMES.RENDERER], | |
1343 ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']]; | |
1344 | |
1345 const pathForThread2 = [ | |
1346 [CHROME_PROCESS_NAMES.GPU], | |
1347 ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']]; | |
1348 | |
1349 const model = buildModelFromSpec(modelSpec); | |
1350 const root = constructMultiDimensionalView(model, model.bounds); | |
1351 const valueForAllThreads = getNodeValues_(root, pathForAllThreads); | |
1352 const valueForThread1 = getNodeValues_(root, pathForThread1); | |
1353 const valueForThread2 = getNodeValues_(root, pathForThread2); | |
1354 | |
1355 assert.closeTo(getCpuUsage_(valueForAllThreads), | |
1356 getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); | |
1357 assert.closeTo(getCpuTotal_(valueForAllThreads), | |
1358 getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); | |
1359 }); | |
1360 | |
1361 test('constructMultiDimensionalView_completeAggregation', () => { | |
1362 const modelSpec = { | |
1363 processes: [ | |
1364 { | |
1365 name: 'Browser', | |
1366 pid: 12345, | |
1367 threads: [ | |
1368 { | |
1369 name: 'CrBrowserMain', | |
1370 tid: 1, | |
1371 slices: (() => { | |
1372 const slices = []; | |
1373 for (let i = 0; i < 1000; i += 50) { | |
1374 slices.push({range: [i, i + 50], cpu: 30}); | |
1375 } | |
1376 return slices; | |
1377 })(), | |
1378 }, | |
1379 ], | |
1380 }, | |
1381 { | |
1382 name: 'Renderer', | |
1383 pid: 20001, | |
1384 threads: [ | |
1385 { | |
1386 name: 'Chrome_ChildIOThread', | |
1387 tid: 42, | |
1388 slices: (() => { | |
1389 const slices = []; | |
1390 for (let i = 0; i < 1000; i += 20) { | |
1391 slices.push({range: [i, i + 10], cpu: 5}); | |
1392 } | |
1393 return slices; | |
1394 })(), | |
1395 }, | |
1396 ], | |
1397 }, | |
1398 { | |
1399 name: 'GPU Process', | |
1400 pid: 30001, | |
1401 threads: [ | |
1402 { | |
1403 name: 'Chrome_ChildIOThread', | |
1404 tid: 52, | |
1405 slices: (() => { | |
1406 const slices = []; | |
1407 for (let i = 0; i < 1000; i += 100) { | |
1408 slices.push({range: [i, i + 80], cpu: 40}); | |
1409 } | |
1410 return slices; | |
1411 })(), | |
1412 }, | |
1413 ] | |
1414 }, | |
1415 ], | |
1416 | |
1417 // [Video A] [Click R] [CSS A] [ CSS A ] | |
1418 // [Scroll R] | |
1419 // [Scroll R] | |
1420 expectations: [ | |
1421 {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, | |
1422 range: [0, 90]}, | |
1423 {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, | |
1424 range: [200, 220]}, | |
1425 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1426 range: [210, 260]}, | |
1427 {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, | |
1428 range: [250, 300]}, | |
1429 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1430 range: [500, 560]}, | |
1431 {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, | |
1432 range: [690, 890]} | |
1433 ], | |
1434 }; | |
1435 | |
1436 const model = buildModelFromSpec(modelSpec); | |
1437 const path = [[], [], ['all_stages'], ['all_initiators']]; | |
1438 const root = constructMultiDimensionalView(model, model.bounds); | |
1439 const values = getNodeValues_(root, path); | |
1440 | |
1441 assert.closeTo(getCpuUsage_(values), | |
1442 (30 * 20 + 5 * 50 + 40 * 10) / 1000, 1e-7); | |
1443 assert.closeTo(getCpuTotal_(values), | |
1444 (30 * 20 + 5 * 50 + 40 * 10), 1e-7); | |
1445 }); | |
163 }); | 1446 }); |
1447 | |
164 </script> | 1448 </script> |
OLD | NEW |