Go

How do you measure and assert allocation counts?

Question 346MediumGo 1.22 to 1.25

In benchmarks, call b.ReportAllocs() or run with -benchmem to get B/op and allocs/op. Since Go 1.24, prefer b.Loop(). It resets the timer automatically and keeps the loop body from being optimised away.

func BenchmarkKey(b *testing.B) {
    b.ReportAllocs()
    buf := make([]byte, 0, 64)
    for b.Loop() {
        buf = keyB(buf[:0], 42, "user")
    }
}

// Unit test that guards against allocation regressions
func TestKeyNoAlloc(t *testing.T) {
    buf := make([]byte, 0, 64)
    allocs := testing.AllocsPerRun(100, func() {
        buf = keyB(buf[:0], 42, "user")
    })
    if allocs != 0 {
        t.Fatalf("keyB allocates %.1f times per call", allocs)
    }
}

Compare runs with benchstat old.txt new.txt over -count=10 samples; a single run is noise. To find where allocations happen, run go test -bench . -memprofile mem.out, then go tool pprof -sample_index=alloc_objects mem.out and use list FuncName.

Gotcha: with the old for i := 0; i < b.N; i++ loop, unused results could be dead-code eliminated, which shows up as a fake "0 allocs, 0.3 ns/op".

More on Memory, GC & Runtime Internals

All 38 Memory, GC & Runtime Internals questions