-
Notifications
You must be signed in to change notification settings - Fork 9.5k
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
Conversation
if (!task.attributableURL || task.attributableURL === 'about:blank') continue; | ||
|
||
const timingByGroupId = result.get(task.attributableURL) || {}; | ||
const original = timingByGroupId[task.group.id] || 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bikeshed: originalTime
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
result.set(eventName, event.selfTime)); | ||
|
||
for (const task of tasks) { | ||
result.set(task.group.id, (result.get(task.group.id) || 0) + task.selfTime * multiplier); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
split second part into a variable(s)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
did the first part
lighthouse-core/lib/task-groups.js
Outdated
taskToGroup, | ||
taskGroups, | ||
taskNameToGroup, | ||
traceEventNames, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
traceEventNames
unused?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I was originally using it to limit the events I had to process in hierarchy but it wasn't a huge perf win, removed
lighthouse-core/lib/task-groups.js
Outdated
* @see https://cs.chromium.org/chromium/src/third_party/blink/renderer/devtools/front_end/timeline/TimelineUIUtils.js?type=cs&q=_initEventStyles+-f:out+f:devtools&sq=package:chromium&g=0&l=39 | ||
*/ | ||
const taskGroups = { | ||
ParseHTML: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to capitalize first letter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
:) but not really, matching DevTools isn't worth much in a removal of DT deps...
|
||
class TraceProcessor { | ||
/** | ||
* @param {LH.TraceEvent} event |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we may need some docs here. What is a task and why does it matter vs an event? Should this just be its own class/file?
text: groupIdToName.scriptParseCompile}, | ||
]; | ||
|
||
const tasks = TraceProcessor.getMainThreadTasks(trace.traceEvents); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be a computed artifact?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah probably, ☠️ 2️⃣ 🐦 1️⃣ 🗿
.map(evt => { | ||
return { | ||
timestamp: evt.ts / 1000, | ||
datauri: `data:image/jpg;base64,${evt.args.snapshot}`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised the compiler doesn't object to accessing snapshot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well I added snapshot to traceevent definition :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant because it was optional but looks like the compiler's ok passing undefined into template strings :)
FYI This is the only one open I'd really want to make sure lands in 3.0 this week @paulirish @brendankenny so we can jump on 3rd party analysis :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job on the main-thread-tasks library. It's hot. There's gonna be demand to ship it standalone. ;)
I think you can remove the console-quieter file now, too. Woo!
Some questions and comments below..
'XHR Load': groupIdToName.scripting, | ||
'XHR Ready State Change': groupIdToName.scripting, | ||
/** | ||
* Make sure the traceEventNames keep up with the ones in DevTools |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious.. did you make any updates for new names this time?
i reviewed https://chromium.googlesource.com/chromium/src/+blame/566d3c11bcb0059ec695185808d33bb4474fb4d7/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js#1156 and only saw one obvious omission aside from some odd crypto ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well the whole list is new :) last time we were keying off the display names, I pulled everything I saw that I recognized/looked like it could be substantial
lighthouse-core/lib/task-groups.js
Outdated
'InvalidateLayout', | ||
'Layout', | ||
'UpdateLayer', | ||
'UpdateLayerTree', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UpdateLayer & UpdateLayerTree belong in paintCompositeRender
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whoops, done
"duration": 63.04200002551079 | ||
"group": "other", | ||
"groupLabel": "Other", | ||
"duration": 177.20099999999977 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW i reviewed these totals and compared them against what perf panel reports.
they lgtm!
|
||
const timingByGroupId = result.get(task.attributableURL) || {}; | ||
const originalTime = timingByGroupId[task.group.id] || 0; | ||
timingByGroupId[task.group.id] = originalTime + task.selfTime * multiplier; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feels weird to apply the multiplier in here.
i know it's another loop, but i'd rather apply the multiplier after we loop over all the tasks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh funny I moved it there because it natural in the computation of time instead of a post-step :)
I don't feel that strongly though, done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ha, it reads better inlined to me too
|
||
for (const task of tasks) { | ||
const originalTime = result.get(task.group.id) || 0; | ||
result.set(task.group.id, originalTime + task.selfTime * multiplier); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment about the inlined multiplier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
MainThreadTasks._computeRecursiveTaskGroup(task); | ||
} | ||
|
||
const firstTs = (tasks[0] || {startTime: 0}).startTime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i've always heard the traceEvents could come out of order, however I know this is more of a case of cross-process events. Perhaps not an issue if everything is within the same thread? We should doublecheck with caseq.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yeah, we should make sure to use the sorted events here 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yeah, we should make sure to use the sorted events here 👍
should this depend on traceOfTab.mainThreadEvents
? Then it doesn't need to check if tasks are in the main thread and they're already sorted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup that was my plan 👍
} | ||
|
||
const firstTs = (tasks[0] || {startTime: 0}).startTime; | ||
for (const task of tasks) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comment
Baselining all times to be relative to start of the trace, and in milliseconds
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lighthouse-core/lib/task-groups.js
Outdated
'UpdateLayerTree', | ||
], | ||
}, | ||
paintCompositeRender: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed you merged together painting & compositing. I'll survive. 😣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah trying to reduce noise for newbs, if you're digging into the savings/differences there it's time for perf panel/chrome tracing 😛
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WFM. plus, i think this distinction matters more in the 60fps/jank case than pageload.
'FireIdleCallback', | ||
'FireAnimationFrame', | ||
'RunMicrotasks', | ||
'V8.Execute', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add 'v8.evaluateModule'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
groups[name] = value * multiplier; | ||
totalBootupTime += value * multiplier; | ||
let bootupTimeForURL = 0; | ||
for (const timespanMs of Object.values(timingByGroupId)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reduce?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not since we're moving the multiplier down, otherwise yes :)
* @return {Map<string, Object<string, number>>} | ||
* @param {LH.Artifacts.TaskNode[]} tasks | ||
* @param {number} multiplier | ||
* @return {Map<string, Object<keyof taskGroups, number>>} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you use keyof
in the Object<>
type (or anything reasonably complicated, it seems), tsc gets confused and promotes to any
, so should use Record<>
here (maybe we should just give up on Object
and always use Record
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
had to widen it to string
anyhow
|
||
const timingByGroupId = result.get(task.attributableURL) || {}; | ||
const originalTime = timingByGroupId[task.group.id] || 0; | ||
timingByGroupId[task.group.id] = originalTime + task.selfTime * multiplier; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ha, it reads better inlined to me too
* Each task will have its group/classification, start time, end time, | ||
* duration, and self time computed. Each task will potentially have a parent, children, and an | ||
* attributeableURL for the script that was executing/forced this execution. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
MainThreadTasks._computeRecursiveTaskGroup(task); | ||
} | ||
|
||
const firstTs = (tasks[0] || {startTime: 0}).startTime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh yeah, we should make sure to use the sorted events here 👍
should this depend on traceOfTab.mainThreadEvents
? Then it doesn't need to check if tasks are in the main thread and they're already sorted
MainThreadTasks._computeRecursiveTaskGroup(task); | ||
} | ||
|
||
const firstTs = (tasks[0] || {startTime: 0}).startTime; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this need the {startTime: 0}
fallback?
@paulirish still requested changes? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
break; | ||
} | ||
|
||
/** @type {string[]} */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: not needed
* | ||
* Each task will have its group/classification, start time, end time, | ||
* duration, and self time computed. Each task will potentially have a parent, children, and an | ||
* attributableURL for the script that was executing/forced this execution. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be attributableURLs
, plural? What does it mean when there's more than one?
Removes 233 KB (48 KB after gzip) from our bundle! |
|
||
let taskURLs = []; | ||
switch (task.event.name) { | ||
case 'v8.compile': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we use the names from task-groups? (or at least add a comment about where these come from)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah I'll add a comment :)
}); | ||
}); | ||
|
||
it('should compute attributableURLs correclty', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
plz spell correctly correctly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
const baseTs = 1241250325; | ||
const url = s => ({args: {data: {url: s}}}); | ||
const stackFrames = f => ({args: {data: {stackTrace: f.map(url => ({url}))}}}); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here i made this for you
/*
An artistic rendering of the below trace:
█████████████████████████████TaskA██████████████████████████████████████████████
████████████████TaskB███████████████████
████EvaluateScript██████
█D█
*/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks 🙏
}); | ||
|
||
it('should compute parent/child correctly', async () => { | ||
const traceEvents = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here i made this for you:
/*
An artistic rendering of the below trace:
█████████████████████████████TaskA██████████████████████████████████████████████
████████████████TaskB███████████████████
███████TaskC██████████
*/
i also made an x-axis but it scale correctly against the box-drawing characters in any monospace fonts except the one i personally use. :(
|----|-----|---|---|------------------|-----------------|--------------------------------------------|-
0 5 10 15 20 40 55 100
|
this was actually quite a bit smoother than network records thanks to how little we used it, I've now confirmed that the numbers reported in the
mainthread-work-breakdown
tests are actually what show up in DevTools for the same trace 🎉(we break scripting out into 3 chunks but 215+25+48=288)
taking CNN as an example, we were previously missing ~16s of main thread time, ~5s of JS bootup time. it previously took ~2s to compute the devtools timeline model, we now do the computations we need (twice) in ~200ms.