Skip to content

perf(block): precompute OTEL for chunker hot paths - #2236

Merged
levb merged 3 commits into
lev-block-cache-bitmapfrom
lev-telemetry-precompute
Mar 27, 2026
Merged

levb merged 3 commits into
lev-block-cache-bitmapfrom
lev-telemetry-precompute

Conversation

@levb

@levb levb commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Replace per-call attribute.String(...) allocation in every Slice/ReadAt/runFetch with precomputed metric.MeasurementOption values built once at package init.

  • Stopwatch.end: build one attribute.NewSet and reuse across all three instrument calls (histogram, sum, count) instead of three separate metric.WithAttributes(kv...) allocations.

  • New PrecomputeAttrs(kv...): builds a reusable MeasurementOption.

  • New Stopwatch.Record(ctx, total, precomputedAttrs): zero per-call attribute allocation alternative to Success/Failure.

  • Exported Success/Failure attribute vars for use with PrecomputeAttrs.

  • Add precomputedAttrs struct with all Slice/fetch attribute combos.

  • Package-level chunkerAttrs var built once at init.

  • All timer.Success(ctx, n, attribute.String(...)) calls replaced with timer.Record(ctx, n, a.successFromCache) etc.

FullFetchChunker.Slice on cache hit (64 MiB cache, 4K blocks, 4 MiB chunks):

                         │    baseline     │         precomputed attrs          │
                         │     sec/op      │   sec/op     vs base              │
ChunkerSlice_CacheHit-16     20.57µ ± 2%   19.85µ ± 3%  -3.49% (p=0.009 n=6)

                         │    baseline     │         precomputed attrs              │
                         │      B/op       │     B/op      vs base                  │
ChunkerSlice_CacheHit-16    9.211Ki ± 0%   8.047Ki ± 0%  -12.64% (p=0.002 n=6)

                         │    baseline     │        precomputed attrs             │
                         │   allocs/op     │ allocs/op   vs base                  │
ChunkerSlice_CacheHit-16     16.000 ± 0%    4.000 ± 0%  -75.00% (p=0.002 n=6)

75% fewer allocations (16 → 4) and 13% less memory per Slice call on the NBD page fault hot path.

@levb levb changed the title perf(telemetry): precompute OTEL for chunker hot paths perf(block): precompute OTEL for chunker hot paths Mar 26, 2026
Comment thread packages/shared/pkg/telemetry/meters.go
@levb
levb marked this pull request as ready for review March 26, 2026 21:32
Replace per-call `attribute.String(...)` allocation in every
`Slice`/`ReadAt`/`runFetch` with precomputed `metric.MeasurementOption`
values built once at package init.

- `Stopwatch.end`: build one `attribute.NewSet` and reuse across all three
  instrument calls (histogram, sum, count) instead of three separate
  `metric.WithAttributes(kv...)` allocations.
- New `PrecomputeAttrs(kv...)`: builds a reusable `MeasurementOption`.
- New `Stopwatch.Record(ctx, total, precomputedAttrs)`: zero per-call
  attribute allocation alternative to `Success`/`Failure`.
- Exported `Success`/`Failure` attribute vars for use with `PrecomputeAttrs`.

- Add `precomputedAttrs` struct with all Slice/fetch attribute combos.
- Package-level `chunkerAttrs` var built once at init.
- All `timer.Success(ctx, n, attribute.String(...))` calls replaced with
  `timer.Record(ctx, n, a.successFromCache)` etc.

FullFetchChunker.Slice on cache hit (64 MiB cache, 4K blocks, 4 MiB chunks):

```
                         │    baseline     │         precomputed attrs          │
                         │     sec/op      │   sec/op     vs base              │
ChunkerSlice_CacheHit-16     20.57µ ± 2%   19.85µ ± 3%  -3.49% (p=0.009 n=6)

                         │    baseline     │         precomputed attrs              │
                         │      B/op       │     B/op      vs base                  │
ChunkerSlice_CacheHit-16    9.211Ki ± 0%   8.047Ki ± 0%  -12.64% (p=0.002 n=6)

                         │    baseline     │        precomputed attrs             │
                         │   allocs/op     │ allocs/op   vs base                  │
ChunkerSlice_CacheHit-16     16.000 ± 0%    4.000 ± 0%  -75.00% (p=0.002 n=6)
```

75% fewer allocations (16 → 4) and 13% less memory per Slice call on the
NBD page fault hot path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@levb
levb force-pushed the lev-telemetry-precompute branch from 1cbb5ad to 155ef71 Compare March 26, 2026 21:39
@levb
levb changed the base branch from main to lev-block-cache-bitmap March 26, 2026 21:40

@dobrac dobrac 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.

few questions

Comment thread packages/orchestrator/pkg/sandbox/block/chunk.go Outdated
Comment thread packages/shared/pkg/telemetry/meters.go
Comment thread packages/shared/pkg/telemetry/meters.go
@dobrac dobrac assigned dobrac and unassigned djeebus Mar 27, 2026
@dobrac dobrac added the improvement Improvement for current functionality label Mar 27, 2026
- renamed `Record` -> `RecordRaw`
- dropped the `a` alias
- refactored `end()` to call `RecordRaw`
@levb
levb requested a review from dobrac March 27, 2026 12:20
@levb
levb merged commit 791950e into lev-block-cache-bitmap Mar 27, 2026
31 checks passed
@levb
levb deleted the lev-telemetry-precompute branch March 27, 2026 12:30
@levb
levb restored the lev-telemetry-precompute branch March 27, 2026 13:11
@levb
levb deleted the lev-telemetry-precompute branch April 7, 2026 21:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improvement for current functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants