Chromium Code Reviews| Index: tracing/tracing/extras/chrome/cpu_time_test.html |
| diff --git a/tracing/tracing/extras/chrome/cpu_time_test.html b/tracing/tracing/extras/chrome/cpu_time_test.html |
| index 5813e39b5de0ae06ea64ff06a3f041c80661e05a..5b0e368f7151f496e5624799bc1deff1f4d1a7c5 100644 |
| --- a/tracing/tracing/extras/chrome/cpu_time_test.html |
| +++ b/tracing/tracing/extras/chrome/cpu_time_test.html |
| @@ -7,6 +7,7 @@ found in the LICENSE file. |
| <link rel="import" href="/tracing/core/test_utils.html"> |
| <link rel="import" href="/tracing/extras/chrome/cpu_time.html"> |
| +<link rel="import" href="/tracing/extras/chrome/cpu_time_test_utils.html"> |
| <script> |
| 'use strict'; |
| @@ -17,6 +18,14 @@ tr.b.unittest.testSuite(function() { |
| const INITIATOR_TYPE = tr.model.um.INITIATOR_TYPE; |
| + const CHROME_PROCESS_NAMES = |
| + tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES; |
| + |
| + const constructMultiDimensionalView = |
| + tr.e.chrome.cpuTime.constructMultiDimensionalView; |
| + |
| + const buildModelFromSpec = tr.e.chrome.cpuTimeTestUtils.buildModelFromSpec; |
| + |
| test('getCpuTimeForThread', () => { |
| const model = tr.c.TestUtils.newModel(function(model) { |
| const thread = model.getOrCreateProcess(1).getOrCreateThread(1); |
| @@ -76,7 +85,8 @@ tr.b.unittest.testSuite(function() { |
| const allSegments = map.get('all_stages').get('all_initiators'); |
| assert.sameDeepMembers( |
| allSegments.map(s => [s.min, s.max]), |
| - [[100, 300], [300, 400], [400, 600]]); |
| + [[100, 300], [300, 400], [400, 600]] |
| + ); |
| const videoAnimationSegments = |
| map.get('Animation').get(INITIATOR_TYPE.VIDEO); |
| @@ -137,7 +147,8 @@ tr.b.unittest.testSuite(function() { |
| const allSegments = map.get('all_stages').get('all_initiators'); |
| assert.sameDeepMembers( |
| allSegments.map(s => [s.min, s.max]), |
| - [[150, 300], [300, 350]]); |
| + [[150, 300], [300, 350]] |
| + ); |
| const videoAnimationSegments = |
| map.get('Animation').get(INITIATOR_TYPE.VIDEO); |
| @@ -160,5 +171,1278 @@ tr.b.unittest.testSuite(function() { |
| // There should be no Response segments |
| assert.isFalse(map.has('Response')); |
| }); |
| + |
| + /** |
| + * 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.
|
| + * the node at |path|. |
| + */ |
| + function getNodeValues_(root, path) { |
| + let node = root; |
| + 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.
|
| + for (const component of path[i]) { |
| + node = node.children[i].get(component); |
| + } |
| + } |
| + return node.values; |
| + } |
| + |
| + const getCpuUsage_ = nodeValues => nodeValues[0].total; |
| + const getCpuTotal_ = nodeValues => nodeValues[1].total; |
| + |
| + /** |
| + * Returns a simple model spec with one process (browser process) and one |
| + * thread (CrBrowserMain). |
| + * |
| + * It does not contain any slices or expectations - those should be added |
| + * manually. |
| + * |
| + * This is a function instead of just a variable because the test functions |
| + * are meant to modify this modelSpec and insert suitable expectations. |
| + */ |
| + function getSimpleModelSpec_() { |
| + return { |
| + processes: [ |
| + { |
| + name: 'Browser', |
| + pid: 12345, |
| + threads: [ |
| + { |
| + name: 'CrBrowserMain', |
| + tid: 1, |
| + slices: [] |
| + }, |
| + ], |
| + }, |
| + ], |
| + expectations: [], |
| + }; |
| + } |
| + |
| + test('constructMultiDimensionalView_' + |
| + 'slicesDoNotStraddleExpecationBoundaries', () => { |
| + const simpleModelSpec = getSimpleModelSpec_(); |
| + simpleModelSpec.processes[0].threads[0].slices.push( |
| + {range: [150, 200], cpu: 30}, |
| + {range: [205, 255], cpu: 20} |
| + ); |
| + simpleModelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, range: [100, 300]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'CSS']]; |
| + |
| + const model = buildModelFromSpec(simpleModelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + 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
|
| + assert.closeTo(getCpuTotal_(values), (30 + 20), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_' + |
| + 'slicesStraddleExpectationBoundaries', () => { |
| + const simpleModelSpec = getSimpleModelSpec_(); |
| + simpleModelSpec.processes[0].threads[0].slices.push( |
| + {range: [150, 200], cpu: 30}, |
| + {range: [205, 255], cpu: 20} |
| + ); |
| + simpleModelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [75, 175]} |
| + ); |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'Video'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(simpleModelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), 15 / 100, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 15, 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_' + |
| + 'singleThread-disjointExpectationsOfSameInitiator', () => { |
| + const simpleModelSpec = getSimpleModelSpec_(); |
| + simpleModelSpec.processes[0].threads[0].slices.push( |
| + {range: [150, 200], cpu: 30}, |
| + {range: [205, 255], cpu: 20} |
| + ); |
| + simpleModelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [100, 160]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [205, 225]} |
| + ); |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Response', 'Scroll'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(simpleModelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + (0.2 * 30 + 0.4 * 20) / (60 + 20), 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + 0.2 * 30 + 0.4 * 20, 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_' + |
| + 'singleThread-overlappingExpectationsOfSameInitiators', () => { |
| + const simpleModelSpec = getSimpleModelSpec_(); |
| + simpleModelSpec.processes[0].threads[0].slices.push( |
| + {range: [150, 200], cpu: 30}, |
| + {range: [205, 255], cpu: 20} |
| + ); |
| + simpleModelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [100, 190]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [160, 230]} |
| + ); |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'CSS'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(simpleModelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (30 + 0.5 * 20) / 130, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 30 + 0.5 * 20, 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_' + |
| + 'singleThread-overlappingExpectationsOfDifferentInitiators', () => { |
| + const simpleModelSpec = getSimpleModelSpec_(); |
| + simpleModelSpec.processes[0].threads[0].slices.push( |
| + {range: [150, 200], cpu: 30}, |
| + {range: [205, 255], cpu: 20} |
| + ); |
| + simpleModelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [100, 190]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [160, 230]} |
| + ); |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(simpleModelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + (30 + 0.5 * 20) / 130, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + 30 + 0.5 * 20, 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_' + |
| + 'singleThread-allStages-customRangeOfInterest', () => { |
| + const simpleModelSpec = getSimpleModelSpec_(); |
| + simpleModelSpec.processes[0].threads[0].slices.push( |
| + {range: [150, 200], cpu: 30}, |
| + {range: [205, 255], cpu: 20} |
| + ); |
| + simpleModelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [100, 190]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [160, 230]} |
| + ); |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['all_stages', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(simpleModelSpec); |
| + const rangeOfInterest = new tr.b.math.Range.fromExplicitRange(100, 210); |
| + const root = constructMultiDimensionalView(model, rangeOfInterest); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (30 + 0.1 * 20) / 110, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 30 + 0.1 * 20, 1e-7); |
| + }); |
| + |
| + /** |
| + * Returns a model spec where the browser process has two worker threads. |
| + * |
| + * This is a function instead of just a variable because the test functions |
| + * are meant to modify this modelSpec and insert suitable expectations. |
| + */ |
| + function getMultipleThreadsOfSameTypeModelSpec_() { |
| + return { |
| + processes: [ |
| + { |
| + name: 'Browser', |
| + pid: 12345, |
| + threads: [ |
| + { |
| + name: 'CrBrowserMain', |
| + tid: 1, |
| + slices: [], |
| + }, |
| + { |
| + name: 'Worker/1', |
| + tid: 42, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 20) { |
| + slices.push({range: [i, i + 10], cpu: 5}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + { |
| + name: 'Worker/2', |
| + tid: 52, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 100) { |
| + slices.push({range: [i, i + 80], cpu: 40}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ], |
| + }, |
| + ], |
| + |
| + expectations: [], |
| + }; |
| + } |
| + |
| + test('constructMultiDimensionalView_multipleThreadsOfSameType_' + |
| + 'singleExpectation', () => { |
| + const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Worker'], ['Animation', 'Video'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 90, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_multipleThreadsOfSameType_' + |
| + 'disjointExpectationSameInitiator', () => { |
| + const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Worker'], ['Animation', 'CSS'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)) / (60 + 200), 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + (5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_multipleThreadsOfSameType_' + |
| + 'overlappingExpectationsOfSameInitiator', () => { |
| + const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Worker'], ['Response', 'Scroll'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + (5 * 4 + 40 * (70 / 80)) / 90, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + 5 * 4 + 40 * (70 / 80), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_multipleThreadsOfSameType_' + |
| + 'disjointExpectationsAllInitiators', () => { |
| + const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Worker'], ['Animation', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + ((5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2))) / |
| + (90 + 60 + 200), 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + (5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)), |
| + 1e-7); |
| + }); |
| + |
| + |
| + test('constructMultiDimensionalView_multipleThreadsOfSameType_' + |
| + 'overlappingExpectationsAllInitiators', () => { |
| + const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); |
| + // [Click R] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Worker'], ['Response', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + (5 * 5 + 40) / 100, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + 5 * 5 + 40, 1e-7); |
| + }); |
| + |
| + |
| + test('constructMultiDimensionalView_multipleThreadsOfSameType_' + |
| + 'allStagesAllInitiators', () => { |
| + const modelSpec = getMultipleThreadsOfSameTypeModelSpec_(); |
| + // [Video A] [Click R] [CSS A] [ CSS A ] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Worker'], ['all_stages', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (250 + 400) / 990, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 250 + 400, 1e-7); |
| + }); |
| + |
| + /** |
| + * Returns a model spec where there are two renderer processes, each with a |
| + * renderer main thread. |
| + * |
| + * This is a function instead of just a variable because the test functions |
| + * are meant to modify this modelSpec and insert suitable expectations. |
| + */ |
| + function getMultipleProcessesOfSameTypeModelSpec_() { |
| + return { |
| + processes: [ |
| + { |
| + name: 'Browser', |
| + pid: 12345, |
| + threads: [ |
| + { |
| + name: 'CrBrowserMain', |
| + tid: 1, |
| + slices: [], |
| + }, |
| + ], |
| + }, |
| + { |
| + name: 'Renderer', |
| + pid: 20001, |
| + threads: [ |
| + { |
| + name: 'CrRendererMain', |
| + tid: 42, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 20) { |
| + slices.push({range: [i, i + 10], cpu: 5}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ], |
| + }, |
| + { |
| + name: 'Renderer', |
| + pid: 30001, |
| + threads: [ |
| + { |
| + name: 'CrRendererMain', |
| + tid: 52, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 100) { |
| + slices.push({range: [i, i + 80], cpu: 40}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ] |
| + }, |
| + ], |
| + |
| + expectations: [], |
| + }; |
| + } |
| + |
| + test('constructMultiDimensionalView_multipleProcessesOfSameType_' + |
| + 'singleExpectation', () => { |
| + const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['CrRendererMain'], ['Animation', 'Video'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 90, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_multipleProcessesOfSameType_' + |
| + 'disjointExpectationSameInitiator', () => { |
| + const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['CrRendererMain'], ['Animation', 'CSS'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)) / (60 + 200), 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + (5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_multipleProcessesOfSameType_' + |
| + 'overlappingExpectationsOfSameInitiator', () => { |
| + const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['CrRendererMain'], ['Response', 'Scroll'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + (5 * 4 + 40 * (70 / 80)) / 90, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + 5 * 4 + 40 * (70 / 80), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_multipleProcessesOfSameType_' + |
| + 'disjointExpectationsAllInitiators', () => { |
| + const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['CrRendererMain'], ['Animation', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + ((5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2))) / |
| + (90 + 60 + 200), 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + (5 * 5 + 40) + ((5 * 3 + 40 * (60 / 80)) + (5 * 10 + 40 * 2)), |
| + 1e-7); |
| + }); |
| + |
| + |
| + test('constructMultiDimensionalView_multipleProcessesOfSameType_' + |
| + 'overlappingExpectationsAllInitiators', () => { |
| + const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); |
| + // [Click R] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['CrRendererMain'], ['Response', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (5 * 5 + 40) / 100, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 5 * 5 + 40, 1e-7); |
| + }); |
| + |
| + |
| + test('constructMultiDimensionalView_multipleProcessesOfSameType_' + |
| + 'allStagesAllInitiators', () => { |
| + const modelSpec = getMultipleProcessesOfSameTypeModelSpec_(); |
| + // [Video A] [Click R] [CSS A] [ CSS A ] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const path = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['CrRendererMain'], ['all_stages', 'all_initiators'] |
| + ]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), (250 + 400) / 990, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), 250 + 400, 1e-7); |
| + }); |
| + |
| + /** |
| + * Returns a model spec where the browser process has a main thread and an IO |
| + * thread. |
| + * |
| + * This is a function instead of just a variable because the test functions |
| + * are meant to modify this modelSpec and insert suitable expectations. |
| + */ |
| + function getAllThreadsOfSameProcessModelSpec_() { |
| + return { |
| + processes: [ |
| + { |
| + name: 'Browser', |
| + pid: 12345, |
| + threads: [ |
| + { |
| + name: 'CrBrowserMain', |
| + tid: 1, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 20) { |
| + slices.push({range: [i, i + 10], cpu: 5}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + { |
| + name: 'Chrome_IOThread', |
| + tid: 5, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 100) { |
| + slices.push({range: [i, i + 80], cpu: 40}); |
| + } |
| + return slices; |
| + })(), |
| + } |
| + ], |
| + }, |
| + ], |
| + |
| + expectations: [], |
| + }; |
| + } |
| + |
| + |
| + test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + |
| + 'singleExpectation', () => { |
| + const modelSpec = getAllThreadsOfSameProcessModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'Video']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'Video']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Chrome_IOThread'], ['Animation', 'Video']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + |
| + 'disjointExpectationSameInitiator', () => { |
| + const modelSpec = getAllThreadsOfSameProcessModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'CSS']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'CSS']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Chrome_IOThread'], ['Animation', 'CSS']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + |
| + 'overlappingExpectationsOfSameInitiator', () => { |
| + const modelSpec = getAllThreadsOfSameProcessModelSpec_(); |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], [], ['Response', 'Scroll']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Response', 'Scroll']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Chrome_IOThread'], ['Response', 'Scroll']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + |
| + 'disjointExpectationsAllInitiators', () => { |
| + const modelSpec = getAllThreadsOfSameProcessModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], [], ['Animation', 'all_initiators']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Animation', 'all_initiators']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Chrome_IOThread'], ['Animation', 'all_initiators']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + |
| + 'overlappingExpectationsAllInitiators', () => { |
| + const modelSpec = getAllThreadsOfSameProcessModelSpec_(); |
| + // [Click R] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], [], ['Response', 'all_initiators']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['Response', 'all_initiators']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Chrome_IOThread'], ['Response', 'all_initiators']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllThreadsOfSameProcess_' + |
| + 'allStagesAllInitiators', () => { |
| + const modelSpec = getAllThreadsOfSameProcessModelSpec_(); |
| + // [Video A] [Click R] [CSS A] [ CSS A ] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], [], ['all_stages', 'all_initiators']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['CrBrowserMain'], ['all_stages', 'all_initiators']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.BROWSER], |
| + ['Chrome_IOThread'], ['all_stages', 'all_initiators']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + /** |
| + * Returns a model spec where a renderer process and a GPU process both have a |
| + * Chrome_ChildIOThread. |
| + * |
| + * This is a function instead of just a variable because the test functions |
| + * are meant to modify this modelSpec and insert suitable expectations. |
| + * |
| + * The modelSpec includes a basic browser process because it not a valid |
| + * chrome model otherwise. |
| + */ |
| + function getAllProcessesOfSameThreadModelSpec_() { |
| + return { |
| + processes: [ |
| + { |
| + name: 'Browser', |
| + pid: 12345, |
| + threads: [ |
| + { |
| + name: 'CrBrowserMain', |
| + tid: 1, |
| + slices: [], |
| + }, |
| + ], |
| + }, |
| + { |
| + name: 'Renderer', |
| + pid: 20001, |
| + threads: [ |
| + { |
| + name: 'Chrome_ChildIOThread', |
| + tid: 42, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 20) { |
| + slices.push({range: [i, i + 10], cpu: 5}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ], |
| + }, |
| + { |
| + name: 'GPU Process', |
| + pid: 30001, |
| + threads: [ |
| + { |
| + name: 'Chrome_ChildIOThread', |
| + tid: 52, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 100) { |
| + slices.push({range: [i, i + 80], cpu: 40}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ] |
| + }, |
| + ], |
| + expectations: [], |
| + }; |
| + } |
| + |
| + test('constructMultiDimensionalView_AllProcessesOfSameThread_' + |
| + 'singleExpectation', () => { |
| + const modelSpec = getAllProcessesOfSameThreadModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [], ['Chrome_ChildIOThread'], ['Animation', 'Video']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['Chrome_ChildIOThread'], ['Animation', 'Video']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.GPU], |
| + ['Chrome_ChildIOThread'], ['Animation', 'Video']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllProcessesOfSameThread_' + |
| + 'disjointExpectationSameInitiator', () => { |
| + const modelSpec = getAllProcessesOfSameThreadModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [], ['Chrome_ChildIOThread'], ['Animation', 'CSS']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['Chrome_ChildIOThread'], ['Animation', 'CSS']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.GPU], |
| + ['Chrome_ChildIOThread'], ['Animation', 'CSS']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllProcessesOfSameThread_' + |
| + 'overlappingExpectationsOfSameInitiator', () => { |
| + const modelSpec = getAllProcessesOfSameThreadModelSpec_(); |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [], ['Chrome_ChildIOThread'], ['Response', 'Scroll']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['Chrome_ChildIOThread'], ['Response', 'Scroll']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.GPU], |
| + ['Chrome_ChildIOThread'], ['Response', 'Scroll']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllProcessesOfSameThread_' + |
| + 'disjointExpectationsAllInitiators', () => { |
| + const modelSpec = getAllProcessesOfSameThreadModelSpec_(); |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [], ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.GPU], |
| + ['Chrome_ChildIOThread'], ['Animation', 'all_initiators']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllProcessesOfSameThread_' + |
| + 'overlappingExpectationsAllInitiators', () => { |
| + const modelSpec = getAllProcessesOfSameThreadModelSpec_(); |
| + // [Click R] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [], ['Chrome_ChildIOThread'], ['Response', 'all_initiators']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['Chrome_ChildIOThread'], ['Response', 'all_initiators']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.GPU], |
| + ['Chrome_ChildIOThread'], ['Response', 'all_initiators']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_AllProcessesOfSameThread_' + |
| + 'allStagesAllInitiators', () => { |
| + const modelSpec = getAllProcessesOfSameThreadModelSpec_(); |
| + // [Video A] [Click R] [CSS A] [ CSS A ] |
| + // [Scroll R] |
| + // [Scroll R] |
| + modelSpec.expectations.push( |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ); |
| + |
| + const pathForAllThreads = [ |
| + [], ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']]; |
| + |
| + const pathForThread1 = [ |
| + [CHROME_PROCESS_NAMES.RENDERER], |
| + ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']]; |
| + |
| + const pathForThread2 = [ |
| + [CHROME_PROCESS_NAMES.GPU], |
| + ['Chrome_ChildIOThread'], ['all_stages', 'all_initiators']]; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const valueForAllThreads = getNodeValues_(root, pathForAllThreads); |
| + const valueForThread1 = getNodeValues_(root, pathForThread1); |
| + const valueForThread2 = getNodeValues_(root, pathForThread2); |
| + |
| + assert.closeTo(getCpuUsage_(valueForAllThreads), |
| + getCpuUsage_(valueForThread1) + getCpuUsage_(valueForThread2), 1e-7); |
| + assert.closeTo(getCpuTotal_(valueForAllThreads), |
| + getCpuTotal_(valueForThread1) + getCpuTotal_(valueForThread2), 1e-7); |
| + }); |
| + |
| + test('constructMultiDimensionalView_completeAggregation', () => { |
| + const modelSpec = { |
| + processes: [ |
| + { |
| + name: 'Browser', |
| + pid: 12345, |
| + threads: [ |
| + { |
| + name: 'CrBrowserMain', |
| + tid: 1, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 50) { |
| + slices.push({range: [i, i + 50], cpu: 30}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ], |
| + }, |
| + { |
| + name: 'Renderer', |
| + pid: 20001, |
| + threads: [ |
| + { |
| + name: 'Chrome_ChildIOThread', |
| + tid: 42, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 20) { |
| + slices.push({range: [i, i + 10], cpu: 5}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ], |
| + }, |
| + { |
| + name: 'GPU Process', |
| + pid: 30001, |
| + threads: [ |
| + { |
| + name: 'Chrome_ChildIOThread', |
| + tid: 52, |
| + slices: (() => { |
| + const slices = []; |
| + for (let i = 0; i < 1000; i += 100) { |
| + slices.push({range: [i, i + 80], cpu: 40}); |
| + } |
| + return slices; |
| + })(), |
| + }, |
| + ] |
| + }, |
| + ], |
| + |
| + // [Video A] [Click R] [CSS A] [ CSS A ] |
| + // [Scroll R] |
| + // [Scroll R] |
| + expectations: [ |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.VIDEO, |
| + range: [0, 90]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.CLICK, |
| + range: [200, 220]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [210, 260]}, |
| + {stage: 'Response', initiatorType: INITIATOR_TYPE.SCROLL, |
| + range: [250, 300]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [500, 560]}, |
| + {stage: 'Animation', initiatorType: INITIATOR_TYPE.CSS, |
| + range: [690, 890]} |
| + ], |
| + }; |
| + |
| + const model = buildModelFromSpec(modelSpec); |
| + const path = [[], [], ['all_stages'], ['all_initiators']]; |
| + const root = constructMultiDimensionalView(model, model.bounds); |
| + const values = getNodeValues_(root, path); |
| + |
| + assert.closeTo(getCpuUsage_(values), |
| + (30 * 20 + 5 * 50 + 40 * 10) / 1000, 1e-7); |
| + assert.closeTo(getCpuTotal_(values), |
| + (30 * 20 + 5 * 50 + 40 * 10), 1e-7); |
| + }); |
| }); |
| + |
| </script> |