Skip to content

Commit 46f6d2a

Browse files
wardpeetpaulirish
authored andcommitted
core(devtools-timeline-model): extract model generation to a computed artifact...
Assert it doesn't mutate the trace, with a few exceptions. Extract timeline task-groups into lib.
1 parent 3bdb56e commit 46f6d2a

File tree

11 files changed

+399
-358
lines changed

11 files changed

+399
-358
lines changed

lighthouse-core/audits/bootup-time.js

Lines changed: 40 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -6,91 +6,9 @@
66
'use strict';
77

88
const Audit = require('./audit');
9-
const DevtoolsTimelineModel = require('../lib/traces/devtools-timeline-model');
109
const WebInspector = require('../lib/web-inspector');
11-
const Util = require('../report/v2/renderer/util.js');
12-
13-
const group = {
14-
loading: 'Network request loading',
15-
parseHTML: 'Parsing DOM',
16-
styleLayout: 'Style & Layout',
17-
compositing: 'Compositing',
18-
painting: 'Paint',
19-
gpu: 'GPU',
20-
scripting: 'Script Evaluation',
21-
scriptParseCompile: 'Script Parsing & Compile',
22-
scriptGC: 'Garbage collection',
23-
other: 'Other',
24-
images: 'Images',
25-
};
26-
const taskToGroup = {
27-
'Animation': group.painting,
28-
'Async Task': group.other,
29-
'Frame Start': group.painting,
30-
'Frame Start (main thread)': group.painting,
31-
'Cancel Animation Frame': group.scripting,
32-
'Cancel Idle Callback': group.scripting,
33-
'Compile Script': group.scriptParseCompile,
34-
'Composite Layers': group.compositing,
35-
'Console Time': group.scripting,
36-
'Image Decode': group.images,
37-
'Draw Frame': group.painting,
38-
'Embedder Callback': group.scripting,
39-
'Evaluate Script': group.scripting,
40-
'Event': group.scripting,
41-
'Animation Frame Fired': group.scripting,
42-
'Fire Idle Callback': group.scripting,
43-
'Function Call': group.scripting,
44-
'DOM GC': group.scriptGC,
45-
'GC Event': group.scriptGC,
46-
'GPU': group.gpu,
47-
'Hit Test': group.compositing,
48-
'Invalidate Layout': group.styleLayout,
49-
'JS Frame': group.scripting,
50-
'Input Latency': group.scripting,
51-
'Layout': group.styleLayout,
52-
'Major GC': group.scriptGC,
53-
'DOMContentLoaded event': group.scripting,
54-
'First paint': group.painting,
55-
'FMP': group.painting,
56-
'FMP candidate': group.painting,
57-
'Load event': group.scripting,
58-
'Minor GC': group.scriptGC,
59-
'Paint': group.painting,
60-
'Paint Image': group.images,
61-
'Paint Setup': group.painting,
62-
'Parse Stylesheet': group.parseHTML,
63-
'Parse HTML': group.parseHTML,
64-
'Parse Script': group.scriptParseCompile,
65-
'Other': group.other,
66-
'Rasterize Paint': group.painting,
67-
'Recalculate Style': group.styleLayout,
68-
'Request Animation Frame': group.scripting,
69-
'Request Idle Callback': group.scripting,
70-
'Request Main Thread Frame': group.painting,
71-
'Image Resize': group.images,
72-
'Finish Loading': group.loading,
73-
'Receive Data': group.loading,
74-
'Receive Response': group.loading,
75-
'Send Request': group.loading,
76-
'Run Microtasks': group.scripting,
77-
'Schedule Style Recalculation': group.styleLayout,
78-
'Scroll': group.compositing,
79-
'Task': group.other,
80-
'Timer Fired': group.scripting,
81-
'Install Timer': group.scripting,
82-
'Remove Timer': group.scripting,
83-
'Timestamp': group.scripting,
84-
'Update Layer': group.compositing,
85-
'Update Layer Tree': group.compositing,
86-
'User Timing': group.scripting,
87-
'Create WebSocket': group.scripting,
88-
'Destroy WebSocket': group.scripting,
89-
'Receive WebSocket Handshake': group.scripting,
90-
'Send WebSocket Handshake': group.scripting,
91-
'XHR Load': group.scripting,
92-
'XHR Ready State Change': group.scripting,
93-
};
10+
const Util = require('../report/v2/renderer/util');
11+
const {groupIdToName, taskToGroup} = require('../lib/task-groups');
9412

9513
class BootupTime extends Audit {
9614
/**
@@ -109,11 +27,10 @@ class BootupTime extends Audit {
10927
}
11028

11129
/**
112-
* @param {!Array<TraceEvent>=} trace
30+
* @param {DevtoolsTimelineModel} timelineModel
11331
* @return {!Map<string, Number>}
11432
*/
115-
static getExecutionTimingsByURL(trace) {
116-
const timelineModel = new DevtoolsTimelineModel(trace);
33+
static getExecutionTimingsByURL(timelineModel) {
11734
const bottomUpByURL = timelineModel.bottomUpGroupBy('URL');
11835
const result = new Map();
11936

@@ -128,7 +45,7 @@ class BootupTime extends Audit {
12845
// eventStyle() returns a string like 'Evaluate Script'
12946
const task = WebInspector.TimelineUIUtils.eventStyle(perTaskPerUrlNode.event);
13047
// Resolve which taskGroup we're using
131-
const groupName = taskToGroup[task.title] || group.other;
48+
const groupName = taskToGroup[task.title] || groupIdToName.other;
13249
const groupTotal = taskGroups[groupName] || 0;
13350
taskGroups[groupName] = groupTotal + (perTaskPerUrlNode.selfTime || 0);
13451
});
@@ -144,46 +61,47 @@ class BootupTime extends Audit {
14461
*/
14562
static audit(artifacts) {
14663
const trace = artifacts.traces[BootupTime.DEFAULT_PASS];
147-
const executionTimings = BootupTime.getExecutionTimingsByURL(trace);
64+
return artifacts.requestDevtoolsTimelineModel(trace).then(devtoolsTimelineModel => {
65+
const executionTimings = BootupTime.getExecutionTimingsByURL(devtoolsTimelineModel);
66+
let totalBootupTime = 0;
67+
const extendedInfo = {};
68+
69+
const headings = [
70+
{key: 'url', itemType: 'url', text: 'URL'},
71+
{key: 'scripting', itemType: 'text', text: groupIdToName.scripting},
72+
{key: 'scriptParseCompile', itemType: 'text', text: groupIdToName.scriptParseCompile},
73+
];
14874

149-
let totalBootupTime = 0;
150-
const extendedInfo = {};
75+
// map data in correct format to create a table
76+
const results = Array.from(executionTimings).map(([url, groups]) => {
77+
// Add up the totalBootupTime for all the taskGroups
78+
totalBootupTime += Object.keys(groups).reduce((sum, name) => sum += groups[name], 0);
79+
extendedInfo[url] = groups;
15180

152-
const headings = [
153-
{key: 'url', itemType: 'url', text: 'URL'},
154-
{key: 'scripting', itemType: 'text', text: group.scripting},
155-
{key: 'scriptParseCompile', itemType: 'text', text: group.scriptParseCompile},
156-
];
81+
const scriptingTotal = groups[groupIdToName.scripting] || 0;
82+
const parseCompileTotal = groups[groupIdToName.scriptParseCompile] || 0;
83+
return {
84+
url: url,
85+
sum: scriptingTotal + parseCompileTotal,
86+
// Only reveal the javascript task costs
87+
// Later we can account for forced layout costs, etc.
88+
scripting: Util.formatMilliseconds(scriptingTotal, 1),
89+
scriptParseCompile: Util.formatMilliseconds(parseCompileTotal, 1),
90+
};
91+
}).sort((a, b) => b.sum - a.sum);
15792

158-
// map data in correct format to create a table
159-
const results = Array.from(executionTimings).map(([url, groups]) => {
160-
// Add up the totalBootupTime for all the taskGroups
161-
totalBootupTime += Object.keys(groups).reduce((sum, name) => sum += groups[name], 0);
162-
extendedInfo[url] = groups;
93+
const tableDetails = BootupTime.makeTableDetails(headings, results);
16394

164-
const scriptingTotal = groups[group.scripting] || 0;
165-
const parseCompileTotal = groups[group.scriptParseCompile] || 0;
16695
return {
167-
url: url,
168-
sum: scriptingTotal + parseCompileTotal,
169-
// Only reveal the javascript task costs
170-
// Later we can account for forced layout costs, etc.
171-
scripting: Util.formatMilliseconds(scriptingTotal, 1),
172-
scriptParseCompile: Util.formatMilliseconds(parseCompileTotal, 1),
96+
score: totalBootupTime < 4000,
97+
rawValue: totalBootupTime,
98+
displayValue: Util.formatMilliseconds(totalBootupTime),
99+
details: tableDetails,
100+
extendedInfo: {
101+
value: extendedInfo,
102+
},
173103
};
174-
}).sort((a, b) => b.sum - a.sum);
175-
176-
const tableDetails = BootupTime.makeTableDetails(headings, results);
177-
178-
return {
179-
score: totalBootupTime < 4000,
180-
rawValue: totalBootupTime,
181-
displayValue: Util.formatMilliseconds(totalBootupTime),
182-
details: tableDetails,
183-
extendedInfo: {
184-
value: extendedInfo,
185-
},
186-
};
104+
});
187105
}
188106
}
189107

lighthouse-core/audits/mainthread-work-breakdown.js

Lines changed: 45 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -12,91 +12,8 @@
1212

1313
const Audit = require('./audit');
1414
const Util = require('../report/v2/renderer/util');
15-
const DevtoolsTimelineModel = require('../lib/traces/devtools-timeline-model');
16-
1715
// We group all trace events into groups to show a highlevel breakdown of the page
18-
const group = {
19-
loading: 'Network request loading',
20-
parseHTML: 'Parsing DOM',
21-
styleLayout: 'Style & Layout',
22-
compositing: 'Compositing',
23-
painting: 'Paint',
24-
gpu: 'GPU',
25-
scripting: 'Script Evaluation',
26-
scriptParseCompile: 'Script Parsing & Compile',
27-
scriptGC: 'Garbage collection',
28-
other: 'Other',
29-
images: 'Images',
30-
};
31-
32-
const taskToGroup = {
33-
'Animation': group.painting,
34-
'Async Task': group.other,
35-
'Frame Start': group.painting,
36-
'Frame Start (main thread)': group.painting,
37-
'Cancel Animation Frame': group.scripting,
38-
'Cancel Idle Callback': group.scripting,
39-
'Compile Script': group.scriptParseCompile,
40-
'Composite Layers': group.compositing,
41-
'Console Time': group.scripting,
42-
'Image Decode': group.images,
43-
'Draw Frame': group.painting,
44-
'Embedder Callback': group.scripting,
45-
'Evaluate Script': group.scripting,
46-
'Event': group.scripting,
47-
'Animation Frame Fired': group.scripting,
48-
'Fire Idle Callback': group.scripting,
49-
'Function Call': group.scripting,
50-
'DOM GC': group.scriptGC,
51-
'GC Event': group.scriptGC,
52-
'GPU': group.gpu,
53-
'Hit Test': group.compositing,
54-
'Invalidate Layout': group.styleLayout,
55-
'JS Frame': group.scripting,
56-
'Input Latency': group.scripting,
57-
'Layout': group.styleLayout,
58-
'Major GC': group.scriptGC,
59-
'DOMContentLoaded event': group.scripting,
60-
'First paint': group.painting,
61-
'FMP': group.painting,
62-
'FMP candidate': group.painting,
63-
'Load event': group.scripting,
64-
'Minor GC': group.scriptGC,
65-
'Paint': group.painting,
66-
'Paint Image': group.images,
67-
'Paint Setup': group.painting,
68-
'Parse Stylesheet': group.parseHTML,
69-
'Parse HTML': group.parseHTML,
70-
'Parse Script': group.scriptParseCompile,
71-
'Other': group.other,
72-
'Rasterize Paint': group.painting,
73-
'Recalculate Style': group.styleLayout,
74-
'Request Animation Frame': group.scripting,
75-
'Request Idle Callback': group.scripting,
76-
'Request Main Thread Frame': group.painting,
77-
'Image Resize': group.images,
78-
'Finish Loading': group.loading,
79-
'Receive Data': group.loading,
80-
'Receive Response': group.loading,
81-
'Send Request': group.loading,
82-
'Run Microtasks': group.scripting,
83-
'Schedule Style Recalculation': group.styleLayout,
84-
'Scroll': group.compositing,
85-
'Task': group.other,
86-
'Timer Fired': group.scripting,
87-
'Install Timer': group.scripting,
88-
'Remove Timer': group.scripting,
89-
'Timestamp': group.scripting,
90-
'Update Layer': group.compositing,
91-
'Update Layer Tree': group.compositing,
92-
'User Timing': group.scripting,
93-
'Create WebSocket': group.scripting,
94-
'Destroy WebSocket': group.scripting,
95-
'Receive WebSocket Handshake': group.scripting,
96-
'Send WebSocket Handshake': group.scripting,
97-
'XHR Load': group.scripting,
98-
'XHR Ready State Change': group.scripting,
99-
};
16+
const {taskToGroup} = require('../lib/task-groups');
10017

10118
class PageExecutionTimings extends Audit {
10219
/**
@@ -115,11 +32,10 @@ class PageExecutionTimings extends Audit {
11532
}
11633

11734
/**
118-
* @param {!Array<TraceEvent>} trace
35+
* @param {!DevtoolsTimelineModel} timelineModel
11936
* @return {!Map<string, number>}
12037
*/
121-
static getExecutionTimingsByCategory(trace) {
122-
const timelineModel = new DevtoolsTimelineModel(trace);
38+
static getExecutionTimingsByCategory(timelineModel) {
12339
const bottomUpByName = timelineModel.bottomUpGroupBy('EventName');
12440

12541
const result = new Map();
@@ -135,43 +51,49 @@ class PageExecutionTimings extends Audit {
13551
*/
13652
static audit(artifacts) {
13753
const trace = artifacts.traces[PageExecutionTimings.DEFAULT_PASS];
138-
const executionTimings = PageExecutionTimings.getExecutionTimingsByCategory(trace);
139-
let totalExecutionTime = 0;
140-
141-
const extendedInfo = {};
142-
const categoryTotals = {};
143-
const results = Array.from(executionTimings).map(([eventName, duration]) => {
144-
totalExecutionTime += duration;
145-
extendedInfo[eventName] = duration;
146-
const groupName = taskToGroup[eventName];
147-
148-
const categoryTotal = categoryTotals[groupName] || 0;
149-
categoryTotals[groupName] = categoryTotal + duration;
15054

151-
return {
152-
category: eventName,
153-
group: groupName,
154-
duration: Util.formatMilliseconds(duration, 1),
155-
};
156-
});
157-
158-
const headings = [
159-
{key: 'group', itemType: 'text', text: 'Category'},
160-
{key: 'category', itemType: 'text', text: 'Work'},
161-
{key: 'duration', itemType: 'text', text: 'Time spent'},
162-
];
163-
results.stableSort((a, b) => categoryTotals[b.group] - categoryTotals[a.group]);
164-
const tableDetails = PageExecutionTimings.makeTableDetails(headings, results);
165-
166-
return {
167-
score: false,
168-
rawValue: totalExecutionTime,
169-
displayValue: Util.formatMilliseconds(totalExecutionTime),
170-
details: tableDetails,
171-
extendedInfo: {
172-
value: extendedInfo,
173-
},
174-
};
55+
return artifacts.requestDevtoolsTimelineModel(trace)
56+
.then(devtoolsTimelineModel => {
57+
const executionTimings = PageExecutionTimings.getExecutionTimingsByCategory(
58+
devtoolsTimelineModel
59+
);
60+
let totalExecutionTime = 0;
61+
62+
const extendedInfo = {};
63+
const categoryTotals = {};
64+
const results = Array.from(executionTimings).map(([eventName, duration]) => {
65+
totalExecutionTime += duration;
66+
extendedInfo[eventName] = duration;
67+
const groupName = taskToGroup[eventName];
68+
69+
const categoryTotal = categoryTotals[groupName] || 0;
70+
categoryTotals[groupName] = categoryTotal + duration;
71+
72+
return {
73+
category: eventName,
74+
group: groupName,
75+
duration: Util.formatMilliseconds(duration, 1),
76+
};
77+
});
78+
79+
const headings = [
80+
{key: 'group', itemType: 'text', text: 'Category'},
81+
{key: 'category', itemType: 'text', text: 'Work'},
82+
{key: 'duration', itemType: 'text', text: 'Time spent'},
83+
];
84+
results.stableSort((a, b) => categoryTotals[b.group] - categoryTotals[a.group]);
85+
const tableDetails = PageExecutionTimings.makeTableDetails(headings, results);
86+
87+
return {
88+
score: false,
89+
rawValue: totalExecutionTime,
90+
displayValue: Util.formatMilliseconds(totalExecutionTime),
91+
details: tableDetails,
92+
extendedInfo: {
93+
value: extendedInfo,
94+
},
95+
};
96+
});
17597
}
17698
}
17799

0 commit comments

Comments
 (0)