What is GOMEMLIMIT and how would you set it in a container?
Question 341HardGo 1.22 to 1.25
GOMEMLIMIT (Go 1.19+), or debug.SetMemoryLimit, sets a soft limit on all memory the Go runtime manages: heap, goroutine stacks and runtime metadata. It does not cover memory allocated by C via cgo or mmap calls made outside the runtime. As total memory approaches the limit, the GC runs more often, whatever GOGC says.
- Soft limit: the runtime will exceed it rather than fail allocations. Only the OS OOM killer is hard.
- Death-spiral protection: GC CPU use is capped at about 50% over a time window. If live data truly exceeds the limit, the program keeps making progress, grows past the limit, and may then get OOM-killed, instead of thrashing forever.
Common patterns:
# Container limit 1 GiB: leave headroom for non-Go memory and spikes
GOMEMLIMIT=900MiB GOGC=100 # GC normally; collect harder only near the limit
# Throughput-oriented: never GC until close to the limit
GOMEMLIMIT=900MiB GOGC=off # dangerous if live heap can approach the limit
debug.SetMemoryLimit(900 << 20) // bytes; math.MaxInt64 disables
What the interviewer is looking for: set it to about 90-95% of the cgroup limit, not 100%. It replaces "memory ballast" hacks. GOGC=off plus a limit suits workloads whose live heap is well below the limit, and it becomes CPU-bound GC thrashing if they are not.
More on Memory, GC & Runtime Internals
- Q339Is Go's GC generational or compacting? What is the "Green Tea" GC?
- Q340What does GOGC control, exactly? What happens with GOGC=off, 50 or 200?
- Q342How do you read a line of
GODEBUG=gctrace=1output? - Q343Why is the process RSS much larger than the heap in use? How does Go return memory to the OS?
- Q344What techniques do you use to reduce allocations in a hot path?
- Q345How does
sync.Poolbehave, and what are its pitfalls?