Go

How do you write a test that fails if a hot path starts allocating? Explain testing.AllocsPerRun and its caveats.

Question 403HardGo 1.22 to 1.25

Benchmarks show allocs/op, but nobody reads benchmark output on every PR. For code that must stay allocation-free (encoders, loggers, request routing), lock it in with a regular unit test using testing.AllocsPerRun(runs, f). It sets GOMAXPROCS(1), calls f once to warm up, then runs it runs times and returns the average number of heap allocations per call.

func appendRecord(dst []byte, id int, status string) []byte {
    dst = append(dst, "id="...)
    dst = strconv.AppendInt(dst, int64(id), 10)
    dst = append(dst, " status="...)
    return append(dst, status...)
}

func TestAppendRecordNoAlloc(t *testing.T) {
    if testing.CoverMode() != "" {
        t.Skip("coverage instrumentation can change allocation behavior")
    }
    buf := make([]byte, 0, 64)
    allocs := testing.AllocsPerRun(1000, func() {
        buf = appendRecord(buf[:0], 42, "ok")
    })
    if allocs != 0 {
        t.Fatalf("appendRecord allocs/op = %v, want 0", allocs)
    }
}

Caveats:

  • The result is an integer average (total mallocs / runs, integer division), so an allocation that happens once every few calls (e.g. amortized buffer growth) reports 0. Use enough runs and a buffer that is already large enough.
  • Don't use it in a test that calls t.Parallel(): it changes GOMAXPROCS and counts every allocation in the process, so concurrent tests pollute the count.
  • Instrumentation changes results: the race detector and coverage can add or move allocations. The standard library skips these tests under -race (via its internal race.Enabled); in your own code, use a build-tagged constant or testing.CoverMode().
  • When it fails, find the cause with go build -gcflags=-m ("escapes to heap") or a -memprofile from the equivalent benchmark.

Interviewer is looking for: turning a performance property into a regression test instead of hoping someone notices a benchmark change.

More on Performance, Profiling & Testing

All 38 Performance, Profiling & Testing questions