Help us shape the future of Go! Take the 2026 Go Developer Survey

go-hotpath

module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: Apache-2.0

README

go-hotpath

Answer the question every latency-sensitive Go system can't: did the GC interfere with my hot path?

Go Version Go Reference CI License

Quick Start · Benchmarks · Integrations · Docs · Releases


A small, dependency-free Go toolkit for detecting, measuring, and controlling garbage-collector interference in latency-sensitive systems — trading engines, exchange infrastructure, feed decoders, real-time services.

Go's GC is good — but a hot path needs to know when it ran and be able to prove a function can't allocate. Today that's tribal knowledge plus closed-loop benchmarks that hide the tail. go-hotpath makes it a first-class API.

Packages

Package What it does Cost
guard Zero-allocation GC-interference windows (Begin/End) + exact ReadMemStats assertions for tests ~450 ns, 0 allocs
bench Open-loop latency harness — coordinated-omission-safe, dual Latency/Service series, GC CPU attribution ~2 ns per record
profile Reversible GOGC/GOMEMLIMIT/GOMAXPROCS control — Apply/Session, SilentWindow, QuietGC, Snapshot startup/boundary
hotpathcheck go vet analyzer enforcing //hotpath:noalloc across packages CI gate

Quick start

go get github.com/0xshikhar/go-hotpath/guard
go get github.com/0xshikhar/go-hotpath/profile
go get github.com/0xshikhar/go-hotpath/bench
go install github.com/0xshikhar/go-hotpath/cmd/hotpathcheck@latest

Production hot path — detect interference in a bounded window:

g := guard.New()                       // once, at init — one per goroutine
w := g.Begin()                         // ~226 ns, zero allocations
processBatch(batch)
if r := w.End(); !r.Quiet() {          // a GC cycle completed inside
	log.Print(r.Explain())             // "2 automatic GC cycle(s) completed…"
}

Tests — exact allocation proof:

guard.Assert(t, func() { book.Apply(&cmd, &ev) })          // STW — tests only
guard.AssertWithin(t, guard.Budget{Allocs: 2, Bytes: 64}, fn)

CI — write-time allocation gate:

//hotpath:noalloc
func (e *Engine) apply(c *Command) { /* annotated helpers only */ }
go vet -vettool=$(which hotpathcheck) ./...   # fails on new alloc sites

Reversible GC control:

s, err := profile.Apply(profile.SilentWindow(512 << 20)) // GOGC=off + limit
if err != nil { log.Fatal(err) }
res := profile.QuietGC()   // collect once at a boundary of your choosing
defer s.Undo()             // restore verified prior settings

Tail-latency measurement:

rep := bench.New(100_000, bench.WithDuration(10*time.Second)).Run(fn)
fmt.Println(rep.String())   // dual Latency/Service series + GC attribution

Benchmarks

An order-book workload at 100k ops/s, open-loop, on an Apple M4 Pro; p99, median of 3 runs. Book C allocates nothing. Four neighbor goroutines in the same process either do nothing, spin without allocating (the control), or allocate:

Book Neighbors go1.22.12 go1.26.8 go1.27.1 GC cycles
C (0 allocs/op) none 3.1 µs 3.2 µs 3.3 µs 0
C 4 busy, non-allocating 2.5 µs 8.5 µs 6.5 µs 0
C 4 allocating 30 µs 33 µs 35 µs ~354
A (~3 allocs/op) 4 allocating 40 µs 34 µs 42 µs ~363

A book that never allocates still takes a ~10× p99 hit from the GC work its neighbors cause, on every toolchain from 1.22 to 1.27, while its service time stays at ~3 µs. Busy neighbors that don't allocate don't reproduce it. The process is the interference boundary, and this is what guard and bench make visible.

Methodology, the instrumentation-overhead table (guard window ~440 ns, bench record ~2 ns, both 0 allocs on all three toolchains), the no-GC-pressure matrix, and caveats: BENCHMARK.md.

Scope — what this does not do

  • Per-goroutine GC exemption is not possible in Go — the GC is process-wide. guard measures interference; it cannot prevent it.
  • //hotpath:noalloc detects syntactic alloc sites — a make the compiler stack-promotes is still flagged, and implicit interface conversions or calls through function values are not seen. testing.AllocsPerRun/guard.Exact is ground truth; the linter is the regression gate.
  • Observed allocation counters are process-wide lower bounds (span-refill granularity) — that's why Exact/Assert exist for tests. Those are exact but still process-wide: don't use them under t.Parallel.
  • profile restores knob values; a GOMAXPROCS pin is one-way (it disables Go 1.25+ cgroup auto-detection permanently).

Requirements

  • Go 1.26+ recommended; minimum Go 1.22. Every package works the same on 1.22–1.27 (benchmarked on 1.22.12, 1.26.8 and 1.27.1 — see BENCHMARK.md).
  • hotpathcheck builds with Go 1.26+ but vets code of any version — go install auto-fetches the toolchain (Go 1.21+).
  • CI: 1.22 / 1.26 / 1.27 × linux/macOS. Zero library dependencies.

Documentation

Doc What
INTEGRATIONS.md Use cases: matching engine, HTTP service, CI gate, bench recipe
BENCHMARK.md Methodology, all measured numbers, per-toolchain results, caveats
doc/public/runtime-surface.md Audited runtime/metrics catalog — what each counter measures and when it updates
Package docs go doc / pkg.go.dev — the API reference

Contributing

See CONTRIBUTING.md. Commit style is conventional (feat:, fix:, docs:…); the zero-alloc benchmarks and the Go 1.22 floor are hard gates.

License

Apache-2.0 — permissive, safe for closed-source integration. Copyright 2026 0xShikhar (https://shikhar.xyz). See LICENSE.

Directories

Path Synopsis
Package bench is an open-loop latency harness for hot paths.
Package bench is an open-loop latency harness for hot paths.
cmd
hotpathcheck module
Package guard answers one question about a window of execution: did the garbage collector interfere?
Package guard answers one question about a window of execution: did the garbage collector interfere?
internal
rtm
Package rtm is hotpath's single door into runtime/metrics.
Package rtm is hotpath's single door into runtime/metrics.
Package profile applies and reverses Go runtime GC settings as a unit.
Package profile applies and reverses Go runtime GC settings as a unit.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL