Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Unified Diff: tracing/tracing/extras/chrome/cpu_time_test.html

Issue 2807243002: Construct Cpu Time MultidimensionalView (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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>

Powered by Google App Engine
This is Rietveld 408576698