【问题标题】:relationship between container_memory_working_set_bytes and process_resident_memory_bytes and total_rsscontainer_memory_working_set_bytes 与 process_resident_memory_bytes 和 total_rss 的关系
【发布时间】:2021-09-18 05:06:32
【问题描述】:

我正在寻找了解的关系

container_memory_working_set_bytes vs process_resident_memory_bytes vs total_rss (container_memory_rss) + file_mapped 以便更好地配备警报系统OOM 的可能性。

考虑到 如果容器/pod 正在运行单个进程执行用 Go 编写的编译程序,这似乎与我的理解不符(这让我现在感到困惑)。

为什么container_memory_working_set_bytesprocess_resident_memory_bytes 之间的差异如此之大(将近10 倍)

还有container_memory_working_set_bytescontainer_memory_rss + file_mapped之间的关系在这里很奇怪,是我没想到的,看了here之后

匿名和交换缓存内存的总量(包括透明的hugepages),它等于memory.status文件中total_rss的值。这不应与真正的驻留集大小或 cgroup 使用的物理内存量相混淆。 rss + file_mapped 将为您提供 cgroup 的常驻集大小。它不包括被换出的内存。只要这些库中的页面实际上在内存中,它就包含来自共享库的内存。它确实包括所有堆栈和堆内存。

所以cgroup的总驻留集大小是rss + file_mapped对于在给定cgroup中运行的容器,这个值怎么小于container_working_set_bytes

这让我觉得这些统计数据不正确。

以下是用于构建上图的 PROMQL

  • process_resident_memory_bytes{container="sftp-downloader"}
  • container_memory_working_set_bytes{container="sftp-downloader"}
  • go_memstats_heap_alloc_bytes{container="sftp-downloader"}
  • container_memory_mapped_file{container="sftp-downloader"} + container_memory_rss{container="sftp-downloader"}

【问题讨论】:

  • go_memstats_heap_inuse_bytes 怎么样?无论如何,container_memory_working_set_bytes 是更值得信赖的指标。
  • 同意,但人们指的是 watch for container_memory_rss 和 working_set 都用于 OOM kill。并且下划线认为我打算了解 rss 与 working_set 的关系
  • 看到这对于我正在寻找的问题没有用

标签: go kubernetes cgroups cadvisor kubernetes-metrics


【解决方案1】:

所以关系似乎是这样的

container_working_set_in_bytes = container_memory_usage_bytes - total_inactive_file

container_memory_usage_bytes顾名思义是指容器使用的总内存(但由于它还包括文件缓存,即操作系统可以在内存压力下释放的inactive_file)减去inactive_file得到container_working_set_in_bytes

container_memory_rsscontainer_working_sets 之间的关系可以用下面的表达式来概括

container_memory_usage_bytes = container_memory_cache + container_memory_rss 

缓存反映存储在当前缓存在内存中的磁盘上的数据。它包含活动+非活动文件(如上所述)

这解释了为什么container_working_set 更高。

参考#1

参考#2

【讨论】:

  • 不确定我是否读错了方程式,但似乎方程式可以重新格式化为 container_working_set_bytes = container_memory_rss + total_active_file container_memory_usage_bytes = container_memory_rss + total_inactive_file + total_active_file 这意味着,conaainer_working_set_bytes 应该始终小于 container_memory_usage_bytes
  • 是的,正确的。由于container_memory_usage_bytes 简而言之也包括缓存,因此container_working_set_bytes 是真正的RSS
  • @bluefog 似乎您错过了方程式中的 container_memory_swap 和内核内存。据我了解,container_working_set_bytes = container_memory_rss + total_active_file + container_memory_swap + 内核内存和 container_memory_usage_bytes = container_memory_rss + total_inactive_file + total_active_file + container_memory_swap + 内核内存
【解决方案2】:

不是一个真正的答案,但仍然是两个不同的点。

this 是否有助于理解图表?

在我的 $dayjob 中,我们遇到了各种不同的问题,即 Go 运行时外部的不同工具如何计算和显示执行用 Go 编写的程序的进程的内存使用情况。
再加上 Go 在 Linux 上的 GC 实际上并没有将释放的内存页面释放到内核,而只是 madvise(2)s 表明这些页面是 MADV_FREE,一个释放大量内存的 GC 循环不会导致任何外部工具(通常是cgroups stats)获取的“进程”RSS 读数发生显着变化。

因此,我们导出了我们自己的指标,这些指标是通过在任何用 Go 编写的主要服务中定期调用 runtime.ReadMemStats(和 runtime/debug.ReadGCStats)获得的——借助专门为此编写的简单包。这些读数反映了 Go 运行时关于其控制的内存的真实想法。

顺便说一句,如果您为容器设置了内存限制,内存统计信息的NextGC 字段非常有用,因为一旦该读数达到或超过您的内存限制,容器中的进程肯定注定要最终被 oom_killer 击落。

【讨论】:

  • 根据那篇文章,我认为 container_memory_rss + mapped_file 将是 cgroup 的真正 RSS,我认为它高于 container_memory_working_set_bytes,但实际上并非如此。
  • 另外,如果我是正确的 golang 1.16 放弃对 madvice 的支持。
  • @Noobie,不,它使用另一个带有madvise(2) 的标志:MADV_DONTNEED instead of MADV_FREE — 基本上恢复了introduced in Go 1.12 的行为。不幸的是,man page 并不清楚对标有madvise(MADV_DONTNEED) 页面的进程的可观察 RSS 读取会发生什么。
  • 如果我阅读正确,它会说明On Linux, the runtime now defaults to releasing memory to the operating system promptly (using MADV_DONTNEED), rather than lazily when the operating system is under memory pressure (using MADV_FREE)这意味着 RSS 等进程级内存统计信息将更准确地反映 Go 进程正在使用的物理内存量The resident set size (RSS) of the calling process will be immediately reduced 然而。`
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-07
  • 2021-04-02
  • 1970-01-01
  • 2015-03-17
  • 2011-10-13
  • 1970-01-01
相关资源
最近更新 更多