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

Perf: memoize collectSubfields #1130

Merged
merged 2 commits into from
Jan 10, 2018
Merged

Perf: memoize collectSubfields #1130

merged 2 commits into from
Jan 10, 2018

Conversation

leebyron
Copy link
Contributor

@leebyron leebyron commented Dec 8, 2017

Collecting subfields occurs after resolving a field's value and before resolving subfield values. This step collects fragment spreads and checks inline fragment conditions. When fetching a list of things, this step is computed with the same inputs and expecting the same outputs for each item in the list. Memoizing ensures the work is done at most once per type returned from a list.

I tested this against the introspection query (which is both synchronous and complex) against a large schema and saw a ~15%-25% reduction in runtime. In practice I don't expect most queries to see this level of speedup as most queries are limited by backend communication and not execution overhead.

@leebyron
Copy link
Contributor Author

leebyron commented Dec 8, 2017

This isn't mergeable as is. A different set of variables could cause skip/include to be calculated differently

@mohawk2
Copy link
Contributor

mohawk2 commented Dec 19, 2017

Observation: introspection queries seem like a given input will always return exactly the same output as there are no external dependencies that could invalidate a cache. Opportunity to cache such queries wholesale?

@leebyron
Copy link
Contributor Author

Observation: introspection queries seem like a given input will always return exactly the same output as there are no external dependencies that could invalidate a cache. Opportunity to cache such queries wholesale?

I'm not sure we ever have enough information to make that kind of decision - it would also require some query analysis ahead of time and marking resolvers as "pure". I think that would be a much much larger change that's out of scope for this PR.

@mohawk2
Copy link
Contributor

mohawk2 commented Dec 19, 2017

Agreed. I had thought of the "pure" thing myself - perhaps as a property of the field. You don't think introspection queries (except for ones with args, which would require thought) are a good candidate for memoising? Seems to me that one thing that you can guarantee in the life of a GraphQL server is it's going to get lots of introspection queries, and memoising those would be a big win.

Collecting subfields occurs after resolving a field's value and before resolving subfield values. This step collects fragment spreads and checks inline fragment conditions. When fetching a list of things, this step is computed with the same inputs and expecting the same outputs for each item in the list. Memoizing ensures the work is done at most once per type returned from a list.

I tested this against the introspection query (which is both synchronous and complex) against a large schema and saw a ~15%-25% reduction in runtime. In practice I don't expect most queries to see this level of speedup as most queries are limited by backend communication and not execution overhead.
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.

3 participants