3

我正在寻找了解的关系

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_bytes如此之大(近 10 倍)process_resident_memory_bytes

和之间的关系在这里container_memory_working_set_bytescontainer_memory_rss + file_mapped很奇怪,我没想到,读完这里

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

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

这让我对这些统计数据感到有些不对劲。

以下是用于构建上述图表的 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"}
4

2 回答 2

3

所以关系似乎是这样的

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_rss和之间的关系container_working_sets可以用下面的表达式来概括

container_memory_usage_bytes = container_memory_cache + container_memory_rss 

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

这解释了为什么container_working_set更高。

参考#1

参考#2

于 2021-07-23T12:34:03.880 回答
0

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

有助于理解图表吗?

在我的 $dayjob 中,我们遇到了各种不同的问题,即 Go 运行时外部的不同工具如何计算和显示执行用 Go 编写的程序的进程的内存使用情况。
再加上 Go 在 Linux 上的 GC 实际上并没有将释放的内存页面释放到内核,而只是madvise(2)这些页面是这样的事实MADV_FREE,一个释放了相当多内存的 GC 周期不会导致任何明显的读数变化外部工具(通常是统计数据)采用的“过程 RSS” cgroups

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

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

于 2021-07-07T16:54:05.380 回答