Skip to content

improve cgroup memory usage calculation to avoid counting purgeable cache#549

Open
dschaaff wants to merge 1 commit into
KumoCorp:mainfrom
dschaaff:cgroup-mem-tracking-improvements
Open

improve cgroup memory usage calculation to avoid counting purgeable cache#549
dschaaff wants to merge 1 commit into
KumoCorp:mainfrom
dschaaff:cgroup-mem-tracking-improvements

Conversation

@dschaaff

@dschaaff dschaaff commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

When running under a cgroup limit, get_cgroup() reported stat.usage_in_bytes (memory.current on v2, memory.usage_in_bytes on v1) as the process memory usage. That counter includes all page cache, including cold reclaimable cache (inactive_file). For a workload that writes logs and spool to disk, cold cache can dominate: on a real pod memory.current was ~51GB while inactive_file was ~46GB and the true non-cache footprint was ~1.8GB. kumod saw usage near its limit, hit get_headroom() == 0, and ran
shrink_ready_queue_due_to_low_mem
and other reductions against pressure that was almost entirely reclaimable cache the kernel would drop before any OOM.

Report the working set instead:

working_set = max(memory.current - inactive_file, anon)

This matches container_memory_working_set_bytes (kubelet/cAdvisor). It still counts everything that can drive an OOM: anonymous memory, dirty page cache, active_file, tmpfs/shm, and slab.

Memory accounting outside of a cgroup is untouched.

Disclosure: I used Claude to aid in the development of this.

…ache

When running under a cgroup limit, get_cgroup() reported
stat.usage_in_bytes (memory.current on v2, memory.usage_in_bytes on v1)
as the process memory usage. That counter includes all page
cache, including cold reclaimable cache (inactive_file). For a
workload that writes logs and spool to disk, cold cache can dominate:
on a real pod memory.current was ~51GB while inactive_file was ~46GB
and the true non-cache footprint was ~1.8GB. kumod saw usage near its
limit, hit get_headroom() == 0, and ran
shrink_ready_queue_due_to_low_mem
and other reductions against pressure that was almost entirely
reclaimable cache the kernel would drop before any OOM.

Report the working set instead:
```
working_set = max(memory.current - inactive_file, anon)
```
This matches container_memory_working_set_bytes (kubelet/cAdvisor) and
the kernel's own reclaimability accounting. It still counts everything
that can drive an OOM: anonymous memory, dirty page cache, active_file,
tmpfs/shm, and slab.

Signed-off-by: Daniel Schaaff <daniel@danielschaaff.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant