-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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(lantern): create network graph from trace (experimental) #16026
Conversation
static async createGraphFromTrace(mainThreadEvents, trace, traceEngineResult, URL) { | ||
// TODO: trace engine should handle this. | ||
static _findServiceWorkerThreads(trace) { | ||
// TODO: trace engine should provide a map of service workers, like it does for workers. |
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.
it's possible that map already includes (same-process) serviceworkers… do you know it doesn't?
regardless having pid matching for it too seems like a requirement.
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.
good catch, by looking at core/test/fixtures/traces/amp-m86.trace.json
I see that service worker threads also get the same events a worker thread does for purposes of WorkersHandler
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 modified this method to account for all workers, so we build our own comprehensive pid/tid worker map.
@@ -53,7 +53,7 @@ function getNodesAndTimingByRequestId(nodeTimings) { | |||
for (const [node, nodeTiming] of nodeTimings) { | |||
if (node.type !== 'network') continue; | |||
|
|||
requestIdToNode.set(node.record.requestId, {node, nodeTiming}); | |||
requestIdToNode.set(node.request.requestId, {node, nodeTiming}); |
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.
yay! i so appreciate this rename. :) thanks
so far the test skips from what I've checked seem to be
|
const redirectedRequest = structuredClone(request); | ||
if (redirectedRequest.timing) { | ||
// TODO: These are surely wrong for when there is more than one redirect. Would be | ||
// simpler if each redirect remembered it's `timing` object in this `redirects` array. |
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.
Just realized that our network requests don't even have timing
when a request is to be redirected. Only gets set onResponse, which we don't get for redirected requests. This code was written against a test case in redirects-test
that did not adhere to that constraint, so this can be disregarded.
I will send a PR that makes sure none of our mock network record tests set a timing on redirected requests, and then update this block of code.
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 did overlook how onRedirectResponse
calls onResponse
, but from what I can tell redirectResponse
never has a timing
object
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.
welll.... sometimes the timing is present on redirectResponse and sometimes its not. so my claim that "redirects don't have timings" is wrong
I'll leave this TODO as a followup, it's gonna be a tricky change to get these timings to match.
@@ -52,6 +52,12 @@ Object { | |||
|
|||
['provided', 'simulate'].forEach(throttlingMethod => { | |||
it(`should fail to compute a value for old trace (${throttlingMethod})`, async () => { | |||
// TODO(15841): fails... but instead w/ "No frames found in trace data" (not NO_LCP). | |||
// ... handle error when calling code uses lantern? or update expected error? idk |
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 not sure this test is particularly useful anymore. At this point any pre-LCP trace is going to be complete foobar and we shouldn't need to maintain that NO_LCP
is always the first error that comes up.
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.
OK - removed
* @return {Map<number, number[]>} | ||
*/ | ||
static _findWorkerThreads(trace) { | ||
// TODO: WorkersHandler in TraceEngine needs to be updated to also include `pid` (only had `tid`). |
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.
Is this why we have this function instead of using the TraceEngine directly?
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.
yes
// There are some minor differences in the fields, accounted for here. | ||
// Most importantly, there seems to be fewer frames in the trace than the equivalent | ||
// events over the CDP. This results in less accuracy in determining the initiator request, | ||
// which means less edges in the graph, which mean worse results. Should fix. |
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 fix
Meaning we should add more info to the trace events?
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.
yes - this is chromium work
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.
Maybe we should track in b/324059246
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.
- initiator (and any relevant js callstack)
i think it is known already that these call stack frames are missing data.
"unit-report": "yarn mocha --testMatch report/**/*-test.js", | ||
"unit-treemap": "yarn mocha --testMatch treemap/**/*-test.js", | ||
"unit-viewer": "yarn mocha --testMatch viewer/**/*-test.js", | ||
"unit-flow": "bash flow-report/test/run-flow-report-tests.sh", | ||
"unit": "yarn unit-flow && yarn mocha", | ||
"unit": "yarn unit-flow && yarn mocha && yarn unit-lantern-trace", |
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 think this will still run the lantern-trace
tests as part of the normal unit test step (in addition to the new CI step you just added). IDK maybe it would be to confusing to separate this so I won't die on this hill.
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 don't want to create a new step to really run all the unit tests locally, when it will go away soon.
} | ||
|
||
traceEvents.push({ | ||
name: 'ResourceReceiveResponse', |
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.
What about ResourceReceivedData
/ ResourceChangePriority
? Do we just not need those for this PR?
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.
ResourceReceivedData
never used by trace engine
ResourceChangePriority
should be added, but may not be necessary. dont think we even set priority / changing priority in unit tests
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.
Assuming all of the TODOs will be addressed as follow-ups before closing #15841 I think this is a really good first step! Thanks Connor!
This PR does not change the default behavior of Lighthouse.
The most interesting part of this PR is
createGraphFromTrace
- given a trace (and TraceEngine result), produces the network records from the trace. Also handles making the CPU nodes too and returns the graph.In Lighthouse, CDP is still used for the network portion of the graph, except in the presence of
INTERNAL_LANTERN_USE_TRACE=1
env variable. This includes the lantern smoke tests. The CI scripts have been modified minimally to run both variants. When we switch to using the trace totally, this internal control should be removed.Note that the unit tests in
core/test/lib/lantern
only use the trace to build the graph -INTERNAL_LANTERN_USE_TRACE
is only for Lighthouse tests.The only change in these Lantern unit test results is
core/test/lib/lantern/metrics/lantern-largest-contentful-paint-test.js
- a minor difference in the results due to missing requests in the trace for pre-flight CORs, which doesn't actually impact the simulation except for having one less sample when estimating the RTT/throughput. Adding these requests to the trace is non-trivial and this change in results does not yet warrant further work.ref #15841