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

new_audit: add long-tasks diagnostic audit for surfacing top long tasks #10736

Merged
merged 23 commits into from
May 28, 2020

Conversation

Beytoven
Copy link
Contributor

@Beytoven Beytoven commented May 8, 2020

Addresses #10705

@Beytoven Beytoven requested a review from a team as a code owner May 8, 2020 23:01
@Beytoven Beytoven requested review from paulirish and removed request for a team May 8, 2020 23:01
@connorjclark
Copy link
Collaborator

@brendankenny @patrickhulce I assume main-thread-tasks is for programmatic usages via HTTP Archive. true? Do we want to keep it? If so, @Beytoven we'll need to make a new audit instead main-thread-long-tasks ...

@patrickhulce
Copy link
Collaborator

Ooh, yeah good catch @connorjclark. It'd be a shame to lose this data. Not only for HA but it's a great diagnostic tool as well. I'm not sure if the visualizations in calibre and such use this or the trace itself.

Would you be able to create a long-tasks specific one @Beytoven ?

@Beytoven Beytoven changed the title core(main-thread-tasks): surface top long tasks as a diagnostic core: new long-tasks diagnostic audit for surfacing top long tasks May 11, 2020

const UIStrings = {
/** Title of a diagnostic LH audit that provides details on the longest running tasks that occur when the page loads. */
title: 'Avoids long-running tasks',
Copy link
Collaborator

@connorjclark connorjclark May 12, 2020

Choose a reason for hiding this comment

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

Since we're just listing the tasks here and not scoring the audit, title should be more declarative than prescriptive: Long main thread tasks should be fine.

description could be Lists the longest tasks on the main thread, useful for identifying worst contributors to input delay ?

Do we need any sort of web.dev url for this? maybe just link to web.dev/tbt ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about linking to tbt, but unsure as I don't want this audit to be seen as specifically for tbt.


const jsURLs = LongTasks.getJavaScriptURLs(networkRecords);
const longtasks = [...tasks].sort((a, b) => b.duration - a.duration)
.filter(t => t.duration >= 50 && t.unbounded === false && !t.parent)
Copy link
Collaborator

Choose a reason for hiding this comment

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

filter, then sort (less work)

.filter(t => t.duration >= 50 && t.unbounded === false && !t.parent)
.slice(0, 20);

const results = longtasks.map(t => ({
Copy link
Collaborator

Choose a reason for hiding this comment

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

t -> task

* @param {Set<string>} jsURLs
* @return {string}
*/
static getAttributableURLForTask(task, jsURLs) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is BootupTime.getAttributableURLForTask right? use that instead?

@@ -1136,12 +1136,6 @@
"lighthouse-core/audits/timing-budget.js | title": {
"message": "Обмеження часу"
},
"lighthouse-core/audits/user-timings.js | columnDuration": {
Copy link
Collaborator

Choose a reason for hiding this comment

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

FYI we will need a string import when this lands @exterkamp

@connorjclark
Copy link
Collaborator

connorjclark commented May 12, 2020

can you add a displayValue that says "1 long task found" / "3 long tasks found" etc., like for the layout shift audit?

after that I think we're good here

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

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

looks great! nice job @Beytoven!

just a few data inclusion and testing nits but LGTM 🎉

@@ -145,62 +169,35 @@ module.exports = [
node: {
type: 'node',
nodeLabel: 'img',
path: '2,HTML,1,BODY,0,IMG',
path: '0,HTML,1,BODY,0,DIV,0,IMG',
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe we should use \d to make this less brittle?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd prefer removing path and instead adding something like src or another unique attribute here (can we match for that in snippet?)

On a quest to reduce paths in smoke tests :) https://github.com/GoogleChrome/lighthouse/pull/10827/files

lighthouse-core/test/audits/long-tasks-test.js Outdated Show resolved Hide resolved
lighthouse-core/test/audits/long-tasks-test.js Outdated Show resolved Hide resolved
lighthouse-core/test/audits/long-tasks-test.js Outdated Show resolved Hide resolved
}
});

it('should populate url when tasks have an attributable url', async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nice touch :)

url: BootupTime.getAttributableURLForTask(task, jsURLs),
group: task.group.label,
start: task.startTime,
self: task.selfTime,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure selfTime is worth including for the toplevel task since anything there is just overhead.

If we include it should we ensure it matches the multiplier too and throw a test on it?

const results = longtasks.map(task => ({
url: BootupTime.getAttributableURLForTask(task, jsURLs),
group: task.group.label,
start: task.startTime,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's going to be weird that startTime is reported on the actual timeline while duration is going to be on the simulated timeline, should we just exclude it for now?


const results = longtasks.map(task => ({
url: BootupTime.getAttributableURLForTask(task, jsURLs),
group: task.group.label,
Copy link
Collaborator

Choose a reason for hiding this comment

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

don't know if group is worth including when it's value is always Other, maybe we exclude it?

Co-authored-by: Patrick Hulce <[email protected]>
@@ -84,6 +84,10 @@ const UIStrings = {
columnOverBudget: 'Over Budget',
/** Label for a column in a data table; entries will be a representation of a DOM element. */
columnElement: 'Element',
/** Label for a column in a data table; entries will be the number of milliseconds since the page started loading. */
columnStartTime: 'Start Time',
Copy link
Collaborator

Choose a reason for hiding this comment

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

technically not needed here but I say keep it b/c it will be needed here in your followup

},
},
},
// TODO: uncomment when Chrome m83 lands
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm ok with removing this but can you make an issue + assign to yourself so we don't forget to add it back when m84 (comment is wrong) lands?

lhr: {
requestedUrl: 'http://localhost:10200/perf/trace-elements.html',
finalUrl: 'http://localhost:10200/perf/trace-elements.html',
audits: {
'largest-contentful-paint-element': {
score: null,
displayValue: '1 element found',
Copy link
Collaborator

Choose a reason for hiding this comment

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

driveby: can you remove displayValue?

devtoolsLogs: {defaultPass: devtoolsLog},
};
const result = await LongTasks.audit(artifacts, {computedCache: new Map()});
// expect(result.score).toBe(0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

remove

*/
function generateTraceWithLongTasks(
count,
duration = 200,
Copy link
Collaborator

Choose a reason for hiding this comment

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

styling nit: we tend to only have line breaks in params if it is too long.

const task = {ts, duration};
task.children = [];
if (withChildTasks) {
task.children.push({
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a comment detailing (or maybe an asci chart) the structure of the child tasks?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea, will do.

const baseTs = 1000;
const traceTasks = [];
for (let i = 1; i <= count; i++) {
const ts = baseTs * i;
Copy link
Collaborator

Choose a reason for hiding this comment

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

looks like tasks start at 1s instead of 0, is that important?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For this case, yes. I want to avoid any overlapping trace events so that no unintentional parent/child task relationships get formed since we need top level tasks for this audit. So starting at 1s avoids any of the added tasks overlapping with the required tasks defined in CreateTestTrace().

});

it('should populate url when tasks have an attributable url', async () => {
const trace = generateTraceWithLongTasks(1, 300, true);
Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe use object parameter? can't tell what these values mean w/o looking at function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants