Skip to content
All writing Part 05 of 11 · 從 19 個 goroutine 到 exit 137
Engineering · 1 min read

記憶體三層模型:cgroup → allocator → heap

RSS 大於 heap inuse 是正常的。中間夾了一層分配器,它拿了記憶體不一定馬上還。三層模型、三套指標。

RSS > heap inuse 是正常的,中間夾了一層分配器,它拿了記憶體不一定馬上還。

三層,三套指標

cgroup (memory.current) RSS + kernel allocations (cache, bufs) memory.high → reclaim · memory.max → OOM allocator (runtime middleman) holds pre-fetched pages from kernel GC frees obj → slot returns HERE (RSS unchanged, heap inuse drops) heap (pprof / runtime metrics) heap_alloc: live objects (precise) heap_inuse: active spans ≥ alloc heap_idle: no live objects heap_sys = inuse + idle

cgroup 層

  • memory.current = 所有實體記憶體:RSS + kernel 分配(file cache、socket buffer)。memory.max = 硬上限,超過 = OOM Kill (exit 137)。
  • 不只看 RSS:kernel-charged memory(大量 socket、file cache)也會推過 memory.max

分配器層

  • new(obj) 不直接 syscall,分配器預先從 kernel 拿 pages,切成 size-class slots。GC 回收物件時,slot 還給分配器,不是還給 kernel,所以 pprof inuse_space 掉了,RSS 不一定掉。

Heap 層(cAdvisor + Go runtime)

  • container_memory_usage_bytes ≈ cgroup memory.currentcontainer_memory_working_set_bytes = K8s 驅逐依據。
  • heap_alloc = 活物件精確位元組。heap_inuse − heap_alloc = 碎片(活物件佔住整個 span)。heap_idle − heap_released = 分配器持有但還沒還給 kernel 的。

在這個 OOM 裡的角色

瀏覽器的記憶體不在這三層裡,它是另一個 process,有自己的 cgroup 帳。Go heap 小不代表 pod 安全;要同時看瀏覽器 sidecar 的 container_memory_usage_bytesOOM 診斷決策樹)。

記憶體有三層真相:application(pprof)→ process(RSS + allocator)→ kernel(cgroup)。哪層大,問題就在哪層。

參考來源:

Related: 參見執行環境OOM 診斷決策樹,或回到系列總覽

Tags #go #concurrency #reliability
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Youtube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration