perf(precompute): avoid cloning the accumulator at window close#379
Merged
Conversation
merge_panes_for_window evicts the oldest pane destructively (it is removed from the map and dropped), but then called take_accumulator(), which clones the inner accumulator before the updater is dropped. For sketch accumulators that clone is expensive (a serialize -> deserialize round-trip), so it is pure waste when the pane is being evicted. Add AccumulatorUpdater::into_accumulator(self: Box<Self>) that moves the inner accumulator out (no clone) and use it for the evicted (oldest) pane. Sliding- window shared panes still snapshot_accumulator() (clone), since a later window may still read them. A default impl falls back to a clone for updaters that can't cheaply move their inner accumulator out. For tumbling windows this removes one accumulator clone per window close. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
milindsrivastava1997
left a comment
Contributor
There was a problem hiding this comment.
Code Review
Correctness:
IncreaseAccumulatorUpdater doesn't use the macro (its acc is Option<_> with special None handling), so it falls through to the default into_accumulator:
fn into_accumulator(self: Box<Self>) -> Box<dyn AggregateCore> {
self.snapshot_accumulator() // default: still clones!
}
But take_accumulator for this type already does a zero-copy move via self.acc.take(). It would be consistent (and correct, not just faster) to override into_accumulator here too:
fn into_accumulator(self: Box<Self>) -> Box<dyn AggregateCore> {
let this = *self;
Box::new(this.acc.unwrap_or_else(|| {
IncreaseAccumulator::new(Measurement::new(0.0), 0, Measurement::new(0.0), 0)
}))
}
IncreaseAccumulator is just scalar fields so the clone is cheap, but the inconsistency is a latent footgun if someone copies the pattern.
Naming:
The macro is called impl_clone_accumulator_methods but now also generates into_accumulator which is explicitly a move, not a clone. The name is now misleading. Worth renaming to impl_accumulator_methods or similar.
…; rename macro Override into_accumulator for IncreaseAccumulatorUpdater so it moves its inner accumulator out (mirroring take_accumulator) instead of falling through to the cloning trait default — consistent with the macro-generated updaters at window close. Rename impl_clone_accumulator_methods -> impl_accumulator_methods, since the macro now also emits the move-based into_accumulator (not just clones). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
milindsrivastava1997
approved these changes
May 28, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
merge_panes_for_windowevicts the oldest pane destructively — it'sremovedfrom the map and dropped — but then called
take_accumulator(), which clonesthe inner accumulator before the updater is dropped. For sketch accumulators that
clone is expensive (a serialize → deserialize round-trip), so it's pure waste
when the pane is being evicted.
This adds
AccumulatorUpdater::into_accumulator(self: Box<Self>)that movesthe inner accumulator out (no clone) and uses it for the evicted (oldest) pane in
merge_panes_for_window. Sliding-window shared panes stillsnapshot_accumulator()(clone), since a later overlapping window may still readthem. A default trait impl falls back to a clone for updaters that can't cheaply
move their inner accumulator out.
For tumbling windows (one pane per window), this removes one accumulator clone
per window close on the ingest hot path.
🤖 Generated with Claude Code