已采纳
回答正文
回复
讨论正文
该问题的正文、回答与讨论。
memory.request=2Gi / memory.limit=2Gi,GOMEMLIMIT=1.8G,GOGC 保持默认 100。凌晨 02:00 起,/sys/fs/cgroup/.../memory.current 从 1.4G 开始缓慢爬升,到次日 02:00 爬到 1.9G(离 limit 只剩 100M),期间 memory.stat 里 file 一直稳在 40M 上下——也就是说这 500M 不是 page cache。
runtime.MemStats.HeapAlloc 稳在 1.18~1.24G,HeapIdle 在 200M~400M 之间,Sys 从 1.5G 缓慢爬到 1.95G。goroutine 数、NumGC、PauseTotal 都没异常,GC 平均 pause 从 3.2ms 缓涨到 6.8ms(还没到报警线)。pmap -x <pid> | sort -k3 -n -r | head -30 抓了爬升前后两次快照:大段 anon 从 12 段涨到 18 段,每段 32~64MB,加起来对得上 500M 的增量。但 smaps 里这些段的 Rss 和 Pss 都真实存在,不是「mmap 占着不用的虚拟空间」。GODEBUG=gctrace=1:GC 触发频率没变,但每次 GC 后 heap idle 的回收量从早期的 ~80MB 降到后期 ~30MB——也就是说 GC 还在跑,但它认为「这些 span 迟早还要用」,没主动 MADV_DONTNEED 归还内核。具体想请教三件事,最好带命令/配置:
GOMEMLIMIT + GOGC + debug.SetGCPercent 的组合能真正让「非 heap 但被 Go 持有」的部分也参与回收?欢迎贴 pmap/smaps 片段、GODEBUG 日志、或者你们线上「Go 服务内存缓慢爬升」的量化案例。我先说:1448 那条问的是 memory.high 水位差怎么设、1441 问的是 GOMEMLIMIT 设成 limit 的多少比例,我这条问的是「GOMEMLIMIT 已经设了、heap 也稳着,但 cgroup 侧还是爬」这个更下游的归因和工具链,跟那两条不重合。