GODEBUG and Runtime Knobs
GODEBUG and Runtime Knobs
Overview
The runtime exposes a surprising amount of behavior through environment variables — especially GODEBUG. These are for diagnosis and carefully controlled experiments, not random production toggles without metrics.
Diagram: Knob layers
flow:
[Runtime]
|
v
[Observe]
Essential Environment
| Variable | Role |
|---|---|
GOMAXPROCS |
P count / parallel Go code |
GOGC |
GC percent trigger |
GOMEMLIMIT |
Soft memory limit |
GODEBUG |
Comma-separated runtime debug flags |
GOTRACEBACK |
Panic stack verbosity (single, all, crash, …) |
GOFLAGS |
Default flags for go command |
GORACE |
Race detector options |
GODEBUG Hits Worth Knowing
Exact keys evolve — check go doc runtime / release notes. Common families:
GODEBUG=gctrace=1 ./app # GC line traces
GODEBUG=schedtrace=1000 ./app # scheduler trace every 1s
GODEBUG=asyncpreemptoff=1 ./app # debug preemption (special)
GODEBUG=http2debug=1 ./app # HTTP/2 verbose (net/http)# init-time print of effective settings sometimes available via:
go envGOTRACEBACK
GOTRACEBACK=all ./app # all goroutines on panic
GOTRACEBACK=crash ./app # extra crash info / abort behavior (platform)Programmatic Knobs
debug.SetGCPercent(50)
debug.SetMemoryLimit(512 << 20)
debug.WriteHeapDump(fd)
runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(1000)Safety Rules
- Change one knob at a time.
- Compare p95 CPU memory goroutines before/after.
- Do not ship
schedtraceorhttp2debugat full verbosity in prod. - Prefer
GOMEMLIMITover folkloreGOGC=off.
Experiment
GODEBUG=gctrace=1 go run .package main
import (
"fmt"
"runtime"
"runtime/debug"
)
func main() {
debug.SetGCPercent(100)
var keep [][]byte
for i := 0; i < 200; i++ {
keep = append(keep, make([]byte, 256*1024))
}
fmt.Println("goroutines", runtime.NumGoroutine(), "kept", len(keep))
keep = nil
runtime.GC()
}What to notice: gctrace lines show GC cycles correlating with allocation bursts.
Try next: Capture schedtrace during a latency incident; look for high latencies in scheduling vs your code.