Skip to content

perf(kv): skip merge of absent context/user/tenant maps in snapshot#138

Merged
samber merged 1 commit into
mainfrom
perf/skip-merge-absent-maps
Jul 5, 2026
Merged

perf(kv): skip merge of absent context/user/tenant maps in snapshot#138
samber merged 1 commit into
mainfrom
perf/skip-merge-absent-maps

Conversation

@samber

@samber samber commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • mergeMaps allocates a fresh map even for empty input, so every snapshot() (called once per ToMap/LogValue/formatVerbose) paid up to three map allocations for context/userData/tenantData fields the error chain never set.
  • Consumers only ever check len() on these fields, so leaving them nil when nothing was merged is equivalent.
  • ToMap's in-place "id" insertion into s.userData/s.tenantData now guards against the nil case explicitly.

Benchmarks

benchstat (darwin/arm64, Apple M3, -count=6 -cpu=1):

            before          after
ToMap       5.120Ki ± 0%    5.073Ki ± 0%  -0.92% (p=0.002 n=6)
LogValue    5.264Ki ± 0%    5.217Ki ± 0%  -0.89% (p=0.002 n=6)
ToMap       62.00 allocs    61.00 allocs  -1.61% (p=0.002 n=6)
LogValue    60.00 allocs    59.00 allocs  -1.67% (p=0.002 n=6)

Wall-clock deltas were not statistically significant on this run (background noise on the benchmark machine), but the B/op and allocs/op reductions are fully reproducible (0% variance, p=0.002).

Test plan

Verified with go build ./..., go vet ./..., and go test ./....

mergeMaps allocates a fresh map even for empty input, so every
snapshot() paid up to three map allocations for fields the error
chain never set. Consumers only ever check len() on these fields, so
leaving them nil is equivalent; ToMap's in-place "id" insertion now
guards against the nil case explicitly.

benchstat (darwin/arm64, Apple M3, -count=6 -cpu=1):

            before          after
ToMap       5.120Ki ± 0%    5.073Ki ± 0%  -0.92% (p=0.002 n=6)
LogValue    5.264Ki ± 0%    5.217Ki ± 0%  -0.89% (p=0.002 n=6)
ToMap       62.00 allocs    61.00 allocs  -1.61% (p=0.002 n=6)
LogValue    60.00 allocs    59.00 allocs  -1.67% (p=0.002 n=6)

Wall-clock deltas were not statistically significant on this run
(background noise on the benchmark machine), but the B/op and
allocs/op reductions are fully reproducible (0% variance, p=0.002).
@samber samber marked this pull request as ready for review July 5, 2026 15:14
Copilot AI review requested due to automatic review settings July 5, 2026 15:14
@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.24%. Comparing base (9be8af4) to head (cfded4d).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
error.go 0.00% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #138      +/-   ##
==========================================
- Coverage   90.43%   90.24%   -0.20%     
==========================================
  Files          15       15              
  Lines        1234     1250      +16     
==========================================
+ Hits         1116     1128      +12     
- Misses         93       95       +2     
- Partials       25       27       +2     
Flag Coverage Δ
unittests 90.24% <60.00%> (-0.20%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI 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.

Pull request overview

This PR reduces per-call allocations in the internal snapshot() path by avoiding unnecessary map merges when the error chain contains no context/user/tenant maps, while preserving existing outward behavior for ToMap, LogValue, and verbose formatting.

Changes:

  • Skip mergeMaps/lazyMapEvaluation/dereferencePointers for context/userData/tenantData when no maps were collected during snapshotting.
  • Update OopsError.ToMap() to safely handle nil s.userData / s.tenantData when only the corresponding ID was set, before inserting "id".

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
kv.go Avoids map merge/allocation work in snapshot() when no context/user/tenant maps exist in the chain.
error.go Guards ToMap()’s in-place "id" insertion against nil snapshot user/tenant maps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@samber samber merged commit 53153e5 into main Jul 5, 2026
11 checks passed
@samber samber deleted the perf/skip-merge-absent-maps branch July 5, 2026 15:17
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