Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core(mainthreadwork): multiply by cpuSlowdownMultiplier #5126

Merged
merged 1 commit into from
May 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions lighthouse-core/audits/bootup-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const Audit = require('./audit');
const WebInspector = require('../lib/web-inspector');
const Util = require('../report/html/renderer/util');
const {groupIdToName, taskToGroup} = require('../lib/task-groups');
const THRESHOLD_IN_MS = 10;

class BootupTime extends Audit {
/**
Expand All @@ -29,14 +28,15 @@ class BootupTime extends Audit {
}

/**
* @return {LH.Audit.ScoreOptions}
* @return {LH.Audit.ScoreOptions & {thresholdInMs: number}}
*/
static get defaultOptions() {
return {
// see https://www.desmos.com/calculator/rkphawothk
// <500ms ~= 100, >2s is yellow, >3.5s is red
scorePODR: 600,
scoreMedian: 3500,
thresholdInMs: 50,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good call.

};
}

Expand Down Expand Up @@ -78,6 +78,7 @@ class BootupTime extends Audit {
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const settings = context.settings || {};
const trace = artifacts.traces[BootupTime.DEFAULT_PASS];
const devtoolsTimelineModel = await artifacts.requestDevtoolsTimelineModel(trace);
const executionTimings = BootupTime.getExecutionTimingsByURL(devtoolsTimelineModel);
Expand All @@ -87,15 +88,22 @@ class BootupTime extends Audit {

const headings = [
{key: 'url', itemType: 'url', text: 'URL'},
{key: 'scripting', itemType: 'text', text: groupIdToName.scripting},
{key: 'scriptParseCompile', itemType: 'text', text: groupIdToName.scriptParseCompile},
{key: 'scripting', granularity: 1, itemType: 'ms', text: groupIdToName.scripting},
{key: 'scriptParseCompile', granularity: 1, itemType: 'ms',
text: groupIdToName.scriptParseCompile},
];

const multiplier = settings.throttlingMethod === 'simulate' ?
settings.throttling.cpuSlowdownMultiplier : 1;
// map data in correct format to create a table
const results = Array.from(executionTimings)
.map(([url, groups]) => {
// Add up the totalBootupTime for all the taskGroups
totalBootupTime += Object.keys(groups).reduce((sum, name) => sum += groups[name], 0);
for (const [name, value] of Object.entries(groups)) {
groups[name] = value * multiplier;
totalBootupTime += value * multiplier;
}

extendedInfo[url] = groups;

const scriptingTotal = groups[groupIdToName.scripting] || 0;
Expand All @@ -105,11 +113,11 @@ class BootupTime extends Audit {
sum: scriptingTotal + parseCompileTotal,
// Only reveal the javascript task costs
// Later we can account for forced layout costs, etc.
scripting: Util.formatMilliseconds(scriptingTotal, 1),
scriptParseCompile: Util.formatMilliseconds(parseCompileTotal, 1),
scripting: scriptingTotal,
scriptParseCompile: parseCompileTotal,
};
})
.filter(result => result.sum >= THRESHOLD_IN_MS)
.filter(result => result.sum >= context.options.thresholdInMs)
.sort((a, b) => b.sum - a.sum);

const summary = {wastedMs: totalBootupTime};
Expand Down
11 changes: 8 additions & 3 deletions lighthouse-core/audits/mainthread-work-breakdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class MainThreadWorkBreakdown extends Audit {
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const settings = context.settings || {};
const trace = artifacts.traces[MainThreadWorkBreakdown.DEFAULT_PASS];

const devtoolsTimelineModel = await artifacts.requestDevtoolsTimelineModel(trace);
Expand All @@ -70,9 +71,13 @@ class MainThreadWorkBreakdown extends Audit {
);
let totalExecutionTime = 0;

const multiplier = settings.throttlingMethod === 'simulate' ?
settings.throttling.cpuSlowdownMultiplier : 1;

const extendedInfo = {};
const categoryTotals = {};
const results = Array.from(executionTimings).map(([eventName, duration]) => {
duration *= multiplier;
totalExecutionTime += duration;
extendedInfo[eventName] = duration;
const groupName = taskToGroup[eventName];
Expand All @@ -83,14 +88,14 @@ class MainThreadWorkBreakdown extends Audit {
return {
category: eventName,
group: groupName,
duration: Util.formatMilliseconds(duration, 1),
duration: duration,
};
});

const headings = [
{key: 'group', itemType: 'text', text: 'Category'},
{key: 'category', itemType: 'text', text: 'Work'},
{key: 'duration', itemType: 'text', text: 'Time spent'},
{key: 'duration', itemType: 'ms', granularity: 1, text: 'Time spent'},
];
// @ts-ignore - stableSort added to Array by WebInspector
results.stableSort((a, b) => categoryTotals[b.group] - categoryTotals[a.group]);
Expand All @@ -105,7 +110,7 @@ class MainThreadWorkBreakdown extends Audit {
return {
score,
rawValue: totalExecutionTime,
displayValue: ['%d\xa0ms', totalExecutionTime],
displayValue: [Util.MS_DISPLAY_VALUE, totalExecutionTime],
details: tableDetails,
extendedInfo: {
value: extendedInfo,
Expand Down
45 changes: 31 additions & 14 deletions lighthouse-core/test/audits/bootup-time-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,60 @@ const acceptableTrace = require('../fixtures/traces/progressive-app-m60.json');
const errorTrace = require('../fixtures/traces/airhorner_no_fcp.json');

describe('Performance: bootup-time audit', () => {
const auditOptions = Object.assign({}, BootupTime.defaultOptions, {thresholdInMs: 10});
const roundedValueOf = (output, name) => {
const value = output.extendedInfo.value[name];
const roundedValue = {};
Object.keys(value).forEach(key => roundedValue[key] = Math.round(value[key] * 10) / 10);
return roundedValue;
};

it('should compute the correct BootupTime values', () => {
const artifacts = Object.assign({
traces: {
[BootupTime.DEFAULT_PASS]: acceptableTrace,
},
}, Runner.instantiateComputedArtifacts());

return BootupTime.audit(artifacts, {options: BootupTime.defaultOptions}).then(output => {
return BootupTime.audit(artifacts, {options: auditOptions}).then(output => {
assert.equal(output.details.items.length, 4);
assert.equal(output.score, 1);
assert.equal(Math.round(output.rawValue), 176);

const roundedValueOf = name => {
const value = output.extendedInfo.value[name];
const roundedValue = {};
Object.keys(value).forEach(key => roundedValue[key] = Math.round(value[key] * 10) / 10);
return roundedValue;
};

assert.deepEqual(roundedValueOf('https://pwa.rocks/script.js'), {[groupIdToName.scripting]: 31.8, [groupIdToName.styleLayout]: 5.5, [groupIdToName.scriptParseCompile]: 1.3});
assert.deepEqual(roundedValueOf('https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW'), {[groupIdToName.scripting]: 25, [groupIdToName.scriptParseCompile]: 5.5, [groupIdToName.styleLayout]: 1.2});
assert.deepEqual(roundedValueOf('https://www.google-analytics.com/plugins/ua/linkid.js'), {[groupIdToName.scripting]: 25.2, [groupIdToName.scriptParseCompile]: 1.2});
assert.deepEqual(roundedValueOf('https://www.google-analytics.com/analytics.js'), {[groupIdToName.scripting]: 40.1, [groupIdToName.scriptParseCompile]: 9.6, [groupIdToName.styleLayout]: 0.2});
assert.deepEqual(roundedValueOf(output, 'https://pwa.rocks/script.js'), {[groupIdToName.scripting]: 31.8, [groupIdToName.styleLayout]: 5.5, [groupIdToName.scriptParseCompile]: 1.3});
assert.deepEqual(roundedValueOf(output, 'https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW'), {[groupIdToName.scripting]: 25, [groupIdToName.scriptParseCompile]: 5.5, [groupIdToName.styleLayout]: 1.2});
assert.deepEqual(roundedValueOf(output, 'https://www.google-analytics.com/plugins/ua/linkid.js'), {[groupIdToName.scripting]: 25.2, [groupIdToName.scriptParseCompile]: 1.2});
assert.deepEqual(roundedValueOf(output, 'https://www.google-analytics.com/analytics.js'), {[groupIdToName.scripting]: 40.1, [groupIdToName.scriptParseCompile]: 9.6, [groupIdToName.styleLayout]: 0.2});

assert.ok(output.details.items.length < Object.keys(output.extendedInfo.value).length,
'Items below 10ms threshold were not filtered out');
'Items below threshold were not filtered out');
});
}).timeout(10000);

it('should compute the correct values when simulated', async () => {
const artifacts = Object.assign({
traces: {defaultPass: acceptableTrace},
}, Runner.instantiateComputedArtifacts());

const options = auditOptions;
const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 3}};
const output = await BootupTime.audit(artifacts, {options, settings});

assert.equal(output.details.items.length, 7);
assert.equal(output.score, 0.99);
assert.equal(Math.round(output.rawValue), 528);

assert.deepEqual(roundedValueOf(output, 'https://pwa.rocks/script.js'), {[groupIdToName.scripting]: 95.3, [groupIdToName.styleLayout]: 16.4, [groupIdToName.scriptParseCompile]: 3.9});
});

it('should get no data when no events are present', () => {
const artifacts = Object.assign({
traces: {
[BootupTime.DEFAULT_PASS]: errorTrace,
},
}, Runner.instantiateComputedArtifacts());

return BootupTime.audit(artifacts, {options: BootupTime.defaultOptions})
return BootupTime.audit(artifacts, {options: auditOptions})
.then(output => {
assert.equal(output.details.items.length, 0);
assert.equal(output.score, 1);
Expand Down
23 changes: 23 additions & 0 deletions lighthouse-core/test/audits/mainthread-work-breakdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,29 @@ describe('Performance: page execution timings audit', () => {
});
});

it('should compute the correct values when simulated', async () => {
const artifacts = Object.assign({
traces: {defaultPass: acceptableTrace},
}, Runner.instantiateComputedArtifacts());

const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 3}};
const output = await PageExecutionTimings.audit(artifacts, {options, settings});
const valueOf = name => Math.round(output.extendedInfo.value[name]);

assert.equal(output.details.items.length, 12);
assert.equal(output.score, 0.93);
assert.equal(Math.round(output.rawValue), 1832);

for (const category in output.extendedInfo.value) {
if (output.extendedInfo.value[category]) {
assert.ok(
Math.abs(valueOf(category) - 3 * acceptableTraceExpectations[category]) < 2,
'should have multiplied value by slowdown multiplier'
);
}
}
});

it('should compute the correct pageExecutionTiming values for the redirect trace', () => {
const artifacts = Object.assign({
traces: {
Expand Down
51 changes: 27 additions & 24 deletions lighthouse-core/test/results/sample_v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@
"mainthread-work-breakdown": {
"score": 0.98,
"displayValue": [
"%d ms",
"%10d ms",
1359.7759999930859
],
"rawValue": 1359.7759999930859,
Expand Down Expand Up @@ -911,80 +911,81 @@
},
{
"key": "duration",
"itemType": "text",
"itemType": "ms",
"granularity": 1,
"text": "Time spent"
}
],
"items": [
{
"category": "Evaluate Script",
"group": "Script Evaluation",
"duration": "1,121 ms"
"duration": 1121.2470000088215
},
{
"category": "Run Microtasks",
"group": "Script Evaluation",
"duration": "7 ms"
"duration": 6.680999994277954
},
{
"category": "XHR Ready State Change",
"group": "Script Evaluation",
"duration": "0 ms"
"duration": 0.026999980211257935
},
{
"category": "XHR Load",
"group": "Script Evaluation",
"duration": "0 ms"
"duration": 0.011000007390975952
},
{
"category": "Layout",
"group": "Style & Layout",
"duration": "89 ms"
"duration": 89.00499999523163
},
{
"category": "Recalculate Style",
"group": "Style & Layout",
"duration": "33 ms"
"duration": 32.57899996638298
},
{
"category": "Parse HTML",
"group": "Parsing HTML & CSS",
"duration": "63 ms"
"duration": 63.04200002551079
},
{
"category": "Parse Stylesheet",
"group": "Parsing HTML & CSS",
"duration": "1 ms"
"duration": 1.3200000524520874
},
{
"category": "Minor GC",
"group": "Garbage collection",
"duration": "20 ms"
"duration": 19.94599997997284
},
{
"category": "DOM GC",
"group": "Garbage collection",
"duration": "6 ms"
"duration": 6.252999991178513
},
{
"category": "Compile Script",
"group": "Script Parsing & Compile",
"duration": "8 ms"
"duration": 7.7519999742507935
},
{
"category": "Update Layer Tree",
"group": "Compositing",
"duration": "4 ms"
"duration": 4.238999992609024
},
{
"category": "Composite Layers",
"group": "Compositing",
"duration": "3 ms"
"duration": 2.732000023126602
},
{
"category": "Paint",
"group": "Paint",
"duration": "5 ms"
"duration": 4.94200000166893
}
]
}
Expand Down Expand Up @@ -1033,33 +1034,35 @@
},
{
"key": "scripting",
"itemType": "text",
"granularity": 1,
"itemType": "ms",
"text": "Script Evaluation"
},
{
"key": "scriptParseCompile",
"itemType": "text",
"granularity": 1,
"itemType": "ms",
"text": "Script Parsing & Compile"
}
],
"items": [
{
"url": "http://localhost:10200/dobetterweb/dbw_tester.html",
"sum": 957.277999997139,
"scripting": "955 ms",
"scriptParseCompile": "3 ms"
"scripting": 954.5010000169277,
"scriptParseCompile": 2.776999980211258
},
{
"url": "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js",
"sum": 81.23699998855591,
"scripting": "80 ms",
"scriptParseCompile": "1 ms"
"scripting": 80.03200000524521,
"scriptParseCompile": 1.2049999833106995
},
{
"url": "http://localhost:10200/zone.js",
"sum": 78.23800000548363,
"scripting": "77 ms",
"scriptParseCompile": "2 ms"
"scripting": 76.56400001049042,
"scriptParseCompile": 1.6739999949932098
}
],
"summary": {
Expand Down