Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions docs/BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ given toolchain, so the gates run in every `go test` without the race
detector, which adds allocations of its own. The gates count the
allocations of the whole test binary, so each measurement starts after a
garbage collection; a collection that earlier tests leave pending would
otherwise add to a figure. The byte ceiling catches a
otherwise add to a figure. No collection runs during a measurement either.
A collection empties the caches of `sync.Pool`, and the measured operation
then allocates what it would have reused, by an amount that depends on when
the collection falls. The byte ceiling catches a
single oversized allocation, such as a fixed buffer, which the allocation
count does not; each byte ceiling is the measured figure rounded up to the
next 64 bytes, because map growth in the in-memory store varies it by a few
Expand All @@ -93,7 +96,7 @@ figures in the other sections were measured with Go 1.25.
| Record StreamWrite of three records | 63 | 7,296 |
| JSONL Decode of three records | 33 | 5,504 |
| Volume ReadAt within one of ten blocks | 41 | 10,816 |
| Volume Commit of one block onto a small volume | 136 | 252,032 |
| Volume Commit of one block onto a small volume | 135 | 252,032 |

A change that exceeds a ceiling fails the test and must justify the increase
in its pull request before the ceiling is raised. A change that reduces a
Expand Down
9 changes: 8 additions & 1 deletion internal/testutil/allocgate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package testutil

import (
"runtime"
"runtime/debug"
"testing"
)

Expand Down Expand Up @@ -34,7 +35,10 @@ const AllocGateCalls = 1 + (gateRuns + 1) + gateRuns
// toolchain, but the race detector adds allocations of its own, so callers
// exclude race builds. Each measurement starts after a garbage collection:
// the figures count the allocations of the whole test binary, and a
// collection that earlier tests leave pending otherwise adds to them. Each
// collection that earlier tests leave pending otherwise adds to them. No
// collection runs during a measurement either: a collection empties the
// caches of sync.Pool, and the operation then allocates what it would have
// reused, by an amount that depends on when the collection falls. Each
// gate logs the ceilings its measured figures call for, so `task gates`
// reports them without an edit to the gate table.
func RunAllocGates(t *testing.T, gates []AllocGate) {
Expand All @@ -43,6 +47,9 @@ func RunAllocGates(t *testing.T, gates []AllocGate) {
t.Run(g.Name, func(t *testing.T) {
op := g.Setup(t)
op()
// A collection still runs on runtime.GC, but none starts on its
// own until the gate restores the collector's target.
defer debug.SetGCPercent(debug.SetGCPercent(-1))
runtime.GC()
allocs := testing.AllocsPerRun(gateRuns, op)
runtime.GC()
Expand Down
2 changes: 1 addition & 1 deletion lode/volume/alloc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (
// in-memory store varies it by a few bytes.
var allocGates = []testutil.AllocGate{
{Name: "ReadAt within one of ten blocks", Allocs: 41, Bytes: 10816, Setup: gateReadAt},
{Name: "Commit of one block onto a small volume", Allocs: 136, Bytes: 252032, Setup: gateCommit},
{Name: "Commit of one block onto a small volume", Allocs: 135, Bytes: 252032, Setup: gateCommit},
}

// TestAllocationGates holds each Volume hot path to its allocation ceiling.
Expand Down
Loading