-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Allow selectively opting out of cache result canonization. #8188
Conversation
Although cache result canonization (#7439) is algorithmically efficient (linear time for tree-shaped results), it does have a computational cost for large result trees, so you might want to disable canonization for exceptionally big queries, if you decide the future performance benefits of result canonization are not worth the initial cost. Fortunately, this implementation allows non-canonical results to be exchaged later for canonical results without recomputing the underlying results, but merely by canonizing the previous results. Of course, this reuse happens only when the cache has not been modified in the meantime (the usual result caching/invalidation story, nothing new), in which case the StoreReader does its best to reuse as many subtrees as it can, if it can't reuse the entire result tree.
Previously, queryInfo.diff would be reused as long as the variables hadn't changed, but changes in other options (like canonizeResults) should also trigger recomputation of cache.diff.
d43f0c1
to
b63cc02
Compare
const other = this.executeSelectionSet.peek(...peekArgs); | ||
|
||
if (other) { | ||
if (canonizeResults) { | ||
return { | ||
...other, | ||
// If we previously read this result without canonizing it, we can | ||
// reuse that result simply by canonizing it now. | ||
result: this.canon.admit(other.result), | ||
}; | ||
} | ||
// If we previously read this result with canonization enabled, we can | ||
// return that canonized result as-is. | ||
return other; | ||
} | ||
|
||
// Finally, if we didn't find any useful previous results, run the real | ||
// execSelectionSetImpl method with the given options. | ||
return this.execSelectionSetImpl(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.
This is the clever part, because it means you could disable canonization for a big query fetched during page load (to avoid the cost of canonization), but later trade up to a canonized version of that same result, without redoing much/any of the underlying execSelectionSetImpl
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.
Very cool @benjamn - looks great! 🎉 Just a reminder to add canonizeResults
to the API docs as well. Thanks!
Although cache result canonization (#7439) is algorithmically efficient (linear time for tree-shaped results), it does have a computational cost for large result trees, so you might want to disable canonization for exceptionally big queries, if you decide the future performance benefits of result canonization are not worth the initial cost.
Fortunately, this implementation allows non-canonical results to be exchanged later for canonical results without recomputing the underlying results, but merely by canonizing the previous results.
Of course, this reuse happens only when the cache has not been modified in the meantime (the usual result caching/invalidation story, nothing new), in which case the
StoreReader
does its best to reuse as many subtrees as it can, when it can't reuse the entire result tree.