Skip to content

perf(gatsby): do not force resolvers to be async #28525

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

Merged
merged 9 commits into from
Dec 9, 2020
Merged

perf(gatsby): do not force resolvers to be async #28525

merged 9 commits into from
Dec 9, 2020

Conversation

pvdz
Copy link
Contributor

@pvdz pvdz commented Dec 8, 2020

Drop the async keyword from the wrappingResolver that wraps all resolvers passed on to graphql. This keyword forces the return value to be a promise, injecting tiny delays in each call. Most of the time you wouldn't notice these but at scale they add up.

In this case a large site was triggering the link resolver 35 million times. Only 1.5 million times did the wrapped resolver return a promise. And graphql will properly deal with promises vs non-promises. So we can drop the keyword.

The PR also updates the linkResolver to take the fast path (when target key is id and the resolver is our own defaultResolver) sync rather than also force it to be async. The defaultResolver already has no async keyword.

Doing so drops roughly 5-10% from the runtime of the site I was testing with (!). Promises can be expensive. They should put a warning sign around them.

@gatsbot gatsbot bot added the status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer label Dec 8, 2020
@pvdz pvdz added topic: performance Related to runtime & build performance topic: scaling builds and removed status: triage needed Issue or pull request that need to be triaged and assigned to a reviewer labels Dec 8, 2020
Copy link
Contributor

@wardpeet wardpeet left a comment

Choose a reason for hiding this comment

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

Nice! Do we have tests in place that test this behaviour to make sure defaultId resolver works as expected?

any,
any
> = function defaultFieldResolver(source, args, context, info) {
function _defaultFieldResolver(source, args, context, info): any {
Copy link
Contributor

Choose a reason for hiding this comment

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

why not keep const & function on same line? Does _defaultFieldResolver still get correct typings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because then a lint rule of premature usage will trigger, which we do not apply to function declarations.

My attempt failed anyways so I'll change it back and move the whole function instead 🤷

@pvdz
Copy link
Contributor Author

pvdz commented Dec 8, 2020

make sure defaultId resolver works as expected?

If I throw inside the function and run tests there will be 16 tests that fail where otherwise tests pass. This applies to both return points.

Copy link
Contributor

@vladar vladar left a comment

Choose a reason for hiding this comment

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

Great stuff! This change warrants a comment that we do this for performance reasons. Also, I've added a couple of suggestions inline.

Copy link
Contributor

@vladar vladar left a comment

Choose a reason for hiding this comment

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

Awesome, thanks! 🥇

@pvdz pvdz merged commit cf06435 into master Dec 9, 2020
@pvdz pvdz deleted the maysync branch December 9, 2020 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: performance Related to runtime & build performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants