Reading cgroup v2 CPU and Memory Limits
Reading cgroup v2 CPU and Memory Limits
Thesis
On unified cgroup v2, the files under your process’s cgroup directory tell you the CPU quota and memory cap the container/orchestrator applied. Reading them beats guessing why Go’s GOMAXPROCS or a JVM heap looks “wrong” inside a pod.
Mental model
/proc/self/cgroup → 0::/path/inside/mount
/sys/fs/cgroup/<path>/
cpu.max → "<quota> <period>" or "max <period>"
memory.max → bytes or "max"
memory.current → current usage (bytes)
cpu.max of max 100000 means unlimited quota with a 100 ms period. A quota of 50000 100000 is half a CPU.
Worked example
Verified on this box (cgroup v2, controllers available):
cut -d: -f3 /proc/self/cgroup
# → /agent (example)
cat /sys/fs/cgroup/cgroup.controllers
cat /sys/fs/cgroup/agent/cpu.max
cat /sys/fs/cgroup/agent/memory.max
cat /sys/fs/cgroup/agent/memory.currentObserved:
controllers: cpuset cpu io memory hugetlb pids
self_cgroup: 0::/agent
cpu.max: max 100000
memory.max: max
memory.current: 6229708800
So this agent cgroup currently has unlimited CPU quota and memory max, with several GB already accounted in memory.current. In Kubernetes you would instead see numeric memory.max and a fractional cpu.max under the pod cgroup.
Trap
Reading /sys/fs/cgroup/cpu.max at the root when your process is in a nested cgroup. Always resolve /proc/self/cgroup first. Also: memory.high vs memory.max — hitting high throttles; hitting max OOMs.
Boring rule
Script the triple: self cgroup path → cpu.max → memory.max (+ memory.current). Feed CPU quota into runtime knobs only after you understand period units (microseconds).
Try this
- Inside a
docker run --cpus=1.5 --memory=512m(on a host where you may), re-read the three files. - Compare with
sysconf(_SC_NPROCESSORS_ONLN)— it often still shows host CPUs. - Read
cpu.stat/memory.eventsafter a throttle or OOM.