Skip to content

perf(precompute): avoid cloning the accumulator at window close#379

Merged
milindsrivastava1997 merged 2 commits into
mainfrom
perf/avoid-clone-window-close
May 28, 2026
Merged

perf(precompute): avoid cloning the accumulator at window close#379
milindsrivastava1997 merged 2 commits into
mainfrom
perf/avoid-clone-window-close

Conversation

@zzylol

@zzylol zzylol commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

merge_panes_for_window evicts the oldest pane destructively — it's 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's pure waste
when the pane is being evicted.

This adds AccumulatorUpdater::into_accumulator(self: Box<Self>) that moves
the inner accumulator out (no clone) and uses it for the evicted (oldest) pane in
merge_panes_for_window. Sliding-window shared panes still
snapshot_accumulator() (clone), since a later overlapping window may still read
them. 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

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>
@zzylol zzylol changed the title precompute: avoid cloning the accumulator at window close perf(precompute): avoid cloning the accumulator at window close May 26, 2026

@milindsrivastava1997 milindsrivastava1997 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 milindsrivastava1997 merged commit 1f2487e into main May 28, 2026
8 checks passed
@milindsrivastava1997 milindsrivastava1997 deleted the perf/avoid-clone-window-close branch May 28, 2026 20:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants