-
Notifications
You must be signed in to change notification settings - Fork 32
Reuse EngineQuerier to reduce allocation pressure #1843
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
Open
DavidLegg
wants to merge
1
commit into
perf/clipper-apgen-translation
Choose a base branch
from
perf/engine-querier-reuse
base: perf/clipper-apgen-translation
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 does almost as much work as building a new engine querier, with the added complexity that now, because this is stateful, there's a chance we forget to reset the querier when needed. I'd like to see profiling data showing that this change makes a noticeable improvement before accepting this.
Uh oh!
There was an error while loading. Please reload this page.
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'll also note that, like on the other PR, a querier shouldn't be a very long-lived object, since it only exists for the duration of a condition or resource invocation. The point of a generational GC is to deal with short-lived objects more efficiently, so without profiling I'd be skeptical that, out of all of the transient objects created over the course of a simulation, the querier is a particular hotspot.)
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.
After talking to Brad a little more, it seems that Claude thinks the main benefit here is in keeping
stateCachearound. That initial size of 32, according to Claude, puts non-negligible pressure on the GC to allocate and deallocate it so often.In my own profiling, I've seen
updateConditioncome up as a hot path before, so the idea that allocations in that function might drive performance isn't totally crazy to me. I'll work with Brad to see if we can get more detailed data on this.Uh oh!
There was an error while loading. Please reload this page.
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.
Interesting. It looks like the
stateCacheis new toperf/clipper-apgen-translation(via 12db906), correct? Do we know whether that improved performance at the time? How was the initial size chosen -- does the cache tend to get filled or does it often need to get resized even larger? The idea of a query cache is a good one in principle, but it seems like we're optimizing an optimization, so it might be worth revisiting the original decision holistically.The other thing I'd say is, by design, this cache probably saves a lot of unnecessary state copies (and, unlike in the other PR, resources and conditions should never be maintaining local mutable state, so there's little to no danger to resources sharing the same cached copy). We're basically saving an allocation for every cache hit, so the cache's own allocation should matter less exactly if the cache is a good optimization.
On the other hand, constantly flushing and recreating the cache during the same simulation instant works directionally against the optimization niche the cache targets. In principle, this cache could be lifted all the way to the engine toplevel, and maintained over the course of a whole
SimulationInstant(covering both conditions and resources). The cache could then be passed to the constructor ofEngineQuerierinstead of maintaining and resetting a whole mutableEngineQuerier.Might be worth investigating. There's a lot of hypotheticals floating around this however, so (and I think we agree here) profiling data is really essential for good decision-making. At minimum, I think pulling the cache out to the engine toplevel and passing it to
EngineQuerieron construction would be a reasonable way to scope the GC and maintenance impact of the cache. The choice of cache invalidation policy would be orthogonal.