【发布时间】:2016-11-24 05:24:00
【问题描述】:
虽然这可能看起来与其他问题重复,但让我解释一下为什么不是。
我希望在达到某个内存限制时让我的应用程序的特定部分正常降级。我可以使用基于剩余可用物理内存的标准,但这并不安全,因为操作系统可能会在达到标准之前开始分页我的应用程序使用的内存,这会认为还有一些物理内存,并保留分配等。出于同样的原因,我不能使用进程当前使用的物理内存量,因为一旦操作系统开始将我换出,我就会继续分配操作系统页面内存,所以数字会不再增长。
出于这个原因,我根据我的应用程序分配的内存量选择了一个标准,即非常接近虚拟内存大小。
这个问题 (How to determine CPU and memory consumption from inside a process?) 提供了查询当前进程使用的虚拟内存量的好方法,我认为这正是我所需要的。
在 Windows 上,我使用 GetProcessMemoryInfo() 和 PrivateUsage 字段,效果很好。
在 Linux 上,我尝试了几件事(如下所列),但都不起作用。虚拟内存使用对我不起作用的原因是因为在 Linux 上的 NVidia 硬件上创建 OpenCL 上下文时会发生一些事情。驱动程序保留了一个足够大的虚拟内存空间区域以容纳所有 RAM、所有交换和所有视频内存。我的猜测是它对统一地址空间和一切都是如此。但这也意味着该进程报告使用了大量内存。例如,在我的系统上,top 将在 VIRT 列中报告 23.3 Gb(12 Gb 的 RAM、6 Gb 的交换空间、2 Gb 的视频内存,这为 NVidia 驱动程序保留了 20 Gb)。
在 OSX 上,通过使用 task_info() 和 virtual_size 字段,我也得到了比预期更大的数字(对于在 Windows 上甚至不接近 1 Gb 的应用程序来说,只有几 Gb),但没有那么大Linux。
所以这是一个大问题:我如何才能获得应用程序分配的内存量?我知道这是一个有点模糊的问题(“分配的内存”是什么意思?),但我很灵活:
- 我更愿意包含应用程序静态数据、代码部分和所有内容,但我可以没有。
- 我更愿意包含为堆栈分配的内存,但我可以不用。
- 我更愿意包含共享库使用的内存,但我可以不用。
- 我真的不关心 mmap 的东西,我可以在那时有或没有。
- 等
真正重要的是这个数字随着动态分配(new、malloc、任何东西)而增长,而在释放内存时缩小(我知道这可能取决于实现)。
我尝试过的事情
这是我尝试和/或想到的几个解决方案,但对我不起作用。
-
从 /proc/self/status 读取
这是 how-to-determine-cpu-and-memory-consumption-from-inside-a-process 建议的方法。但是,如上所述,这会返回虚拟内存量,这对我不起作用。
-
从 /proc/self/statm 读取
非常轻微最差:根据http://kernelnewbies.kernelnewbies.narkive.com/iG9xCmwB/proc-pid-statm-doesnt-match-with-status,它指的是Linux内核代码,这两个值之间的唯一区别是第二个值没有减去
reserved_vm到虚拟量记忆。我希望reserved_vm包含 OpenCL 驱动程序保留的内存,但它没有。 -
使用
mallinfo()和uordblks字段这似乎不包括所有分配(我猜
news 丢失了),因为虚拟内存空间增长了+2Gb(在做了一些内存繁重的工作并仍然持有内存之后) ,我只看到mallinfo()返回的数字增长了大约 0.1Gb。 -
从 /proc/self/smaps 读取 [heap] 部分大小
这个值从大约 336,760 Kb 开始,峰值为 1,019,496 Kb,用于将虚拟内存空间增加 +2Gb 的工作,然后它永远不会下降,所以我不确定我是否真的不能依赖这个数字。 .
-
监控我的应用程序中的所有内存分配
是的,在理想的世界中,我可以控制所有分配内存的人。然而,这是一个遗留应用程序,使用大量不同的分配器,一些
mallocs,一些news,一些特定于操作系统的例程等。有一些插件可以做任何他们想做的事情,他们可能是使用不同的编译器等编译。因此,虽然这对于真正控制内存非常有用,但这在我的上下文中不起作用。 -
读取OpenCL上下文初始化前后的虚拟内存大小
虽然这可能是解决问题的一种“hacky”方式(我可能不得不回退到它),但我真的希望有一种更可靠的方式来查询内存,因为 OpenCL 上下文可以在我的某个地方初始化控制,以及其他类似但非 OpenCL 特定的问题可能会蔓延,我不会知道。
所以这就是我所拥有的。还有一件事我还没有尝试过,因为它只适用于OSX,但它是使用Why does mstats and malloc_zone_statistics not show recovered memory after free?中描述的方法,即使用malloc_get_all_zones()和malloc_zone_statistics(),但我认为这可能是同一个问题如mallinfo(),即不考虑所有分配。
那么,任何人都可以建议一种方法来查询 Linux(以及 OSX,即使它是不同的方法)中给定进程的内存使用情况(这个术语很模糊,请参阅上面的精确度)?
【问题讨论】:
-
mallinfo() with (arena + hblkhd + uordblks)
-
@brianbeuning :根据man7.org/linux/man-pages/man3/mallinfo.3.html,
arena是uordblks+fordblks,所以你的建议最终会计算一些内存两次......