-
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(fr): add computed cache to pass context #12427
Conversation
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 love the removal of computed artifact dependency on auditing! Anything that brings our misnomer computed artifacts closer to their true memoized functions existence, SGTM :)
Also heads up, I would expect you to need to update the various FR runners as well to use the computed cache.
types/gatherer.d.ts
Outdated
/** Gatherers can push to this array to add top-level warnings to the LHR. */ | ||
LighthouseRunWarnings: Array<string | IcuMessage>; | ||
baseArtifacts: BaseArtifacts; | ||
} | ||
|
||
export type CompatibilityContext = PassContext | FRTransitionalContext; |
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.
FRTransitionalContext
was supposed to be the minimal set of shared context ("The limited context interface shared between pre and post Fraggle Rock Lighthouse.").
I get that dependencies
somewhat violated that by always being {}
, and I'm guessing that's what prompted this addition? I like the explicitness. Perhaps we should enforce that at the shared FRGatherer implementation level? Like if the meta
contains dependencies throw an error in afterPass
that it must be overriden to handle dependencies?
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.
How do you feel about these changes adding dependencies: {}
to PassContext
?
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 that solves the issue I have in mind, but maybe it's aligned and just doesn't affect things, so I'm open to it.
I'm thinking all afterPass
methods should be typed PassContext
and all getArtifact
should be typed FRTransitionalContext
. In base-gatherer
's afterPass
method at runtime we check if there are any dependencies defined in the meta, if there are we throw an error immediately and don't invoke the other methods.
From that lens it doesn't really matter if dependencies
is defined on PassContext
because nothing is going to attempt to access dependencies on something that is typed PassContext
anyway.
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.
Ah I think I see now.
const context = { | ||
computedCache: passContext.computedCache, | ||
settings: passContext.settings, | ||
options: {}, |
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.
In the first attempt at sharing, I believe a primary objection was the references to these other pieces of state that computed artifacts have.
There's no reason computed artifacts actually need settings
or options
it's just an artifact (heh) of the fact that audits always have access to this information. If we remove both of those from the typedefs (which we should to make it more generic and lower the burden of additional context here), context can be used directly without this intermediate object.
We only have two computed artifacts to fix to remove this requirement.
lighthouse-core/computed/metrics/timing-summary.js:34:74
lighthouse-core/computed/resource-summary.js:56:53 (which was just a minor mistake in the first place)
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.
Actually it's more than two. Timing summary needs settings
to request a bunch of lantern metrics, which use settings.throttlingMethod
. So we need to fix LanternMetric
as well.
Nevermind, I see they don't use the settings from context.
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.
lighthouse-core/computed/metrics/timing-summary.js:34:74
this one's a pretty serious bug that luckily we don't end up triggering. If someone requested timing-summary with the same trace but once with mobileSlow4G
and once with desktopDense4G
, they'd get the same answers back because caching is only on the trace and devtoolsLog :/
The intention was definitely to only pass along the computedCache
, but the type should have been more prescriptive that that was the case rather than just optimizing for ease of use.
Yeah, it's not. |
This seems like a natural extension of and need for artifact dependencies, so generally LGTM. |
One thing I'd like to see in general, though, is less use of computed artifacts :)
In any case, we should move away from defaulting shared functions to computed artifacts unless measured performance during development warrants it, and if a function is slow enough to warrant a computed artifact, we should still be working to speed it up because--even with caching--we're still paying for that computation somewhere the first time it's run. |
So this PR is doing three things now:
I think I am going to move item 1 to a separate PR, and focus on the remaining items in this PR. |
This reverts commit 42e04dd.
@@ -51,6 +51,7 @@ async function startTimespan(options) { | |||
{ | |||
url: finalUrl, | |||
config, | |||
computedCache: new Map(), |
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 we be sharing computed artifacts between phases?
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, but I don't imagine it will really matter in practice as there are no dependencies
for anything but getArtifact
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.
sweet!
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!
Gatherers that use
networkRecords
inloadData
will not have access tonetworkRecords
ingetArtifact
. Our options to resolve this are:computedCache
available in gatherers and request theNetworkRecords
like a normal computed artifact.NetworkRecords
into a FR gatherer and reference it as a dependency.I haven't experimented much with option 3, not sure if it's even possible. This PR does option 2, using
LinkElements
as an example for what this will look like.