Skip to content

Commit

Permalink
core: remove dependency on DevtoolsTimelineModel (#5533)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickhulce committed Jun 28, 2018
1 parent 6e82902 commit 341f0a8
Show file tree
Hide file tree
Showing 21 changed files with 737 additions and 803 deletions.
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

0 comments on commit 341f0a8

Please sign in to comment.