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: remove dependency on DevtoolsTimelineModel #5533

Merged
merged 10 commits into from
Jun 28, 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
114 changes: 62 additions & 52 deletions lighthouse-core/audits/bootup-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
'use strict';

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 {taskGroups} = require('../lib/task-groups');

class BootupTime extends Audit {
/**
Expand Down Expand Up @@ -41,33 +40,40 @@ class BootupTime extends Audit {
}

/**
* Returns a mapping of URL to counts of event groups.
* @param {LH.Artifacts.DevtoolsTimelineModel} timelineModel
* @param {LH.WebInspector.NetworkRequest[]} records
*/
static getJavaScriptURLs(records) {
/** @type {Set<string>} */
const urls = new Set();
for (const record of records) {
if (record._resourceType && record._resourceType === 'Script') {
urls.add(record.url);
}
}

return urls;
}

/**
* @param {LH.Artifacts.TaskNode[]} tasks
* @param {Set<string>} jsURLs
* @return {Map<string, Object<string, number>>}
*/
static getExecutionTimingsByURL(timelineModel) {
const bottomUpByURL = timelineModel.bottomUpGroupBy('URL');
static getExecutionTimingsByURL(tasks, jsURLs) {
/** @type {Map<string, Object<string, number>>} */
const result = new Map();

bottomUpByURL.children.forEach((perUrlNode, url) => {
// when url is "" or about:blank, we skip it
if (!url || url === 'about:blank') {
return;
}
for (const task of tasks) {
const jsURL = task.attributableURLs.find(url => jsURLs.has(url));
const fallbackURL = task.attributableURLs[0];
const attributableURL = jsURL || fallbackURL;
if (!attributableURL || attributableURL === 'about:blank') continue;

/** @type {Object<string, number>} */
const taskGroups = {};
perUrlNode.children.forEach((perTaskPerUrlNode) => {
// eventStyle() returns a string like 'Evaluate Script'
const task = WebInspector.TimelineUIUtils.eventStyle(perTaskPerUrlNode.event);
// Resolve which taskGroup we're using
const groupName = taskToGroup[task.title] || groupIdToName.other;
const groupTotal = taskGroups[groupName] || 0;
taskGroups[groupName] = groupTotal + (perTaskPerUrlNode.selfTime || 0);
});
result.set(url, taskGroups);
});
const timingByGroupId = result.get(attributableURL) || {};
const originalTime = timingByGroupId[task.group.id] || 0;
timingByGroupId[task.group.id] = originalTime + task.selfTime;
result.set(attributableURL, timingByGroupId);
}

return result;
}
Expand All @@ -80,47 +86,54 @@ class BootupTime extends Audit {
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);
let totalBootupTime = 0;
/** @type {Object<string, Object<string, number>>} */
const extendedInfo = {};

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

const devtoolsLog = artifacts.devtoolsLogs[BootupTime.DEFAULT_PASS];
const networkRecords = await artifacts.requestNetworkRecords(devtoolsLog);
const tasks = await artifacts.requestMainThreadTasks(trace);
const multiplier = settings.throttlingMethod === 'simulate' ?
settings.throttling.cpuSlowdownMultiplier : 1;
// map data in correct format to create a table

const jsURLs = BootupTime.getJavaScriptURLs(networkRecords);
const executionTimings = BootupTime.getExecutionTimingsByURL(tasks, jsURLs);

let totalBootupTime = 0;
const results = Array.from(executionTimings)
.map(([url, groups]) => {
.map(([url, timingByGroupId]) => {
// Add up the totalBootupTime for all the taskGroups
for (const [name, value] of Object.entries(groups)) {
groups[name] = value * multiplier;
totalBootupTime += value * multiplier;
let bootupTimeForURL = 0;
for (const [groupId, timespanMs] of Object.entries(timingByGroupId)) {
timingByGroupId[groupId] = timespanMs * multiplier;
bootupTimeForURL += timespanMs * multiplier;
}

// Add up all the execution time of shown URLs
if (bootupTimeForURL >= context.options.thresholdInMs) {
totalBootupTime += bootupTimeForURL;
}

extendedInfo[url] = groups;
const scriptingTotal = timingByGroupId[taskGroups.scriptEvaluation.id] || 0;
const parseCompileTotal = timingByGroupId[taskGroups.scriptParseCompile.id] || 0;

const scriptingTotal = groups[groupIdToName.scripting] || 0;
const parseCompileTotal = groups[groupIdToName.scriptParseCompile] || 0;
return {
url: url,
sum: scriptingTotal + parseCompileTotal,
// Only reveal the javascript task costs
// Later we can account for forced layout costs, etc.
total: bootupTimeForURL,
// Highlight the JavaScript task costs
scripting: scriptingTotal,
scriptParseCompile: parseCompileTotal,
};
})
.filter(result => result.sum >= context.options.thresholdInMs)
.sort((a, b) => b.sum - a.sum);
.filter(result => result.total >= context.options.thresholdInMs)
.sort((a, b) => b.total - a.total);

const summary = {wastedMs: totalBootupTime};

const headings = [
{key: 'url', itemType: 'url', text: 'URL'},
{key: 'total', granularity: 1, itemType: 'ms', text: 'Total'},
{key: 'scripting', granularity: 1, itemType: 'ms', text: taskGroups.scriptEvaluation.label},
{key: 'scriptParseCompile', granularity: 1, itemType: 'ms',
text: taskGroups.scriptParseCompile.label},
];

const details = BootupTime.makeTableDetails(headings, results, summary);

const score = Audit.computeLogNormalScore(
Expand All @@ -134,9 +147,6 @@ class BootupTime extends Audit {
rawValue: totalBootupTime,
displayValue: [Util.MS_DISPLAY_VALUE, totalBootupTime],
details,
extendedInfo: {
value: extendedInfo,
},
};
}
}
Expand Down
54 changes: 23 additions & 31 deletions lighthouse-core/audits/mainthread-work-breakdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@

const Audit = require('./audit');
const Util = require('../report/html/renderer/util');
// We group all trace events into groups to show a highlevel breakdown of the page
const {taskToGroup} = require('../lib/task-groups');
const {taskGroups} = require('../lib/task-groups');

class MainThreadWorkBreakdown extends Audit {
/**
Expand Down Expand Up @@ -43,15 +42,17 @@ class MainThreadWorkBreakdown extends Audit {
}

/**
* @param {LH.Artifacts.DevtoolsTimelineModel} timelineModel
* @param {LH.Artifacts.TaskNode[]} tasks
* @return {Map<string, number>}
*/
static getExecutionTimingsByCategory(timelineModel) {
const bottomUpByName = timelineModel.bottomUpGroupBy('EventName');

static getExecutionTimingsByGroup(tasks) {
/** @type {Map<string, number>} */
const result = new Map();
bottomUpByName.children.forEach((event, eventName) =>
result.set(eventName, event.selfTime));

for (const task of tasks) {
const originalTime = result.get(task.group.id) || 0;
result.set(task.group.id, originalTime + task.selfTime);
}

return result;
}
Expand All @@ -65,40 +66,34 @@ class MainThreadWorkBreakdown extends Audit {
const settings = context.settings || {};
const trace = artifacts.traces[MainThreadWorkBreakdown.DEFAULT_PASS];

const devtoolsTimelineModel = await artifacts.requestDevtoolsTimelineModel(trace);
const executionTimings = MainThreadWorkBreakdown.getExecutionTimingsByCategory(
devtoolsTimelineModel
);
let totalExecutionTime = 0;

const tasks = await artifacts.requestMainThreadTasks(trace);
const multiplier = settings.throttlingMethod === 'simulate' ?
settings.throttling.cpuSlowdownMultiplier : 1;

const extendedInfo = {};
const executionTimings = MainThreadWorkBreakdown.getExecutionTimingsByGroup(tasks);

let totalExecutionTime = 0;
const categoryTotals = {};
const results = Array.from(executionTimings).map(([eventName, duration]) => {
duration *= multiplier;
const results = Array.from(executionTimings).map(([groupId, rawDuration]) => {
const duration = rawDuration * multiplier;
totalExecutionTime += duration;
extendedInfo[eventName] = duration;
const groupName = taskToGroup[eventName];

const categoryTotal = categoryTotals[groupName] || 0;
categoryTotals[groupName] = categoryTotal + duration;
const categoryTotal = categoryTotals[groupId] || 0;
categoryTotals[groupId] = categoryTotal + duration;

return {
category: eventName,
group: groupName,
group: groupId,
groupLabel: taskGroups[groupId].label,
duration: duration,
};
});

const headings = [
{key: 'group', itemType: 'text', text: 'Category'},
{key: 'category', itemType: 'text', text: 'Work'},
{key: 'duration', itemType: 'ms', granularity: 1, text: 'Time spent'},
{key: 'groupLabel', itemType: 'text', text: 'Category'},
{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]);

results.sort((a, b) => categoryTotals[b.group] - categoryTotals[a.group]);
const tableDetails = MainThreadWorkBreakdown.makeTableDetails(headings, results);

const score = Audit.computeLogNormalScore(
Expand All @@ -112,9 +107,6 @@ class MainThreadWorkBreakdown extends Audit {
rawValue: totalExecutionTime,
displayValue: [Util.MS_DISPLAY_VALUE, totalExecutionTime],
details: tableDetails,
extendedInfo: {
value: extendedInfo,
},
};
}
}
Expand Down
25 changes: 0 additions & 25 deletions lighthouse-core/gather/computed/dtm-model.js

This file was deleted.

Loading