Skip to content

perf: add enqueue_many so a wide record takes one buffer lock, not one per channel - #322

Merged
drake-nominal merged 1 commit into
mainfrom
perf/enqueue-many
Aug 27, 2026
Merged

perf: add enqueue_many so a wide record takes one buffer lock, not one per channel#322
drake-nominal merged 1 commit into
mainfrom
perf/enqueue-many

Conversation

@drake-nominal

Copy link
Copy Markdown
Contributor

Stacked on #320. Core-crate change — additive, no existing signature changes.

What it does

Writing N channels at one timestamp took N capacity reservations and N buffer lock acquisitions,
one per channel, though they all belong in the same request. enqueue_many admits the batch under
one reservation and one lock.

Oversized batches are admitted in pieces capped at max_points_per_record, so one call can neither
build a request larger than that limit nor hold the buffer lock longer than a record's worth of
work. has_capacity deliberately lets an oversized batch into an empty buffer — correct for a
single channel's series, but wrong for a batch assembled from thousands of channels, where nothing
else bounds it. A batch that already fits is admitted whole, so a wide record keeps the guarantee
that its channels share a request, and one channel's series is never split across requests.

Results

Against the staging backend, on top of #320, 6,480 channels at one timestamp, interleaved A/B
over three rounds:

#320 + this PR
CPU per million points 0.487 s 0.437 s ~10% less
Throughput 2.12 Mp/s 2.17 Mp/s within noise

Throughput is unchanged because staging is network-bound at this rate — the win here is CPU. Set
expectations accordingly: this is a modest, real improvement on top of #320's 4.6x, not another
multiple.

Tests

Three new unit tests: every channel of a wide record lands in one request; an oversized batch is
split with no request exceeding max_points_per_record and no points lost; and a channel reached
through both enqueue and enqueue_many shares one series rather than splitting.

🤖 Generated with Claude Code

…e per channel

Writing N channels at one timestamp meant N capacity reservations and N buffer lock
acquisitions, one per channel, even though they all belong in the same request.
`enqueue_many` admits the whole batch under one reservation and one lock.

A batch larger than `max_points_per_record` is admitted in pieces rather than all at once, so a
single call can neither build a request larger than that limit nor hold the buffer lock for
longer than a record's worth of work. `has_capacity` deliberately lets an oversized batch into an
empty buffer, which is right for one channel's series but wrong for a batch assembled from
thousands of channels, where nothing else would bound it. A batch that already fits -- the case
this exists for -- is admitted whole, so a wide record keeps the guarantee that all its channels
share a request, and one channel's series is still never split.

Measured against the staging backend on top of the direct-enqueue change, 6,480 channels at one
timestamp, interleaved A/B over three rounds:

  CPU per million points   0.487s -> 0.437s   ~10% less
  throughput               2.12 Mp/s -> 2.17 Mp/s   within noise; staging is network-bound here

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@drake-nominal
drake-nominal merged commit 1fc50de into main Aug 27, 2026
5 checks passed
@drake-nominal
drake-nominal deleted the perf/enqueue-many branch August 27, 2026 01:16
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