GOMEMLIMIT for a low-traffic Go container: choosing a value without automatic cgroup v2 detection
0 reputation · 06 Oct 2021, 20:16 UTC
Goal
I run a low-traffic Go HTTP service in a cgroup v2 container (Kubernetes, memory limit 256Mi) and want to shrink its idle memory footprint to cut costs. Go 1.19+ offers GOMEMLIMIT as a soft memory limit that makes the GC more aggressive, but the runtime does not automatically read cgroup v2 memory.max to populate it.
Constraints and uncertainty
Because detection is manual, the value must stay synchronized with the deployment manifest. The common heuristic is 80–90% of the container limit, but GOMEMLIMIT is soft: allocation bursts can exceed it, and setting it too low increases GC CPU usage, which could offset the savings. It also does not cover CGO allocations or runtime metadata. I can observe /gc/heap/goal:bytes and /memory/classes/total:bytes via runtime/metrics to confirm the effect.
Questions
- For a mostly idle service under a 256Mi cgroup v2 limit, what GOMEMLIMIT value balances RSS reduction against GC CPU overhead, and how should I verify the tradeoff?
- Is there a supported way to derive GOMEMLIMIT from the cgroup limit at startup (e.g., reading /sys/fs/cgroup/memory.max and calling debug.SetMemoryLimit), or is a static env var preferred?
- Which runtime metrics best confirm the limit is working before I commit the change?