监视器未显示正确的内存使用情况

Monitor not showing the right memory usage

我想知道如何使用任何类型的资源监视器 htop top 等来跟踪进程的内存使用情况。让我们写一个简单的C程序。

int main() {
    while(1){}
    return 0;
}

编译后可执行输出a.out只有16Kb

$ ls -lah ./a.out                                                                                                                                           [8:43:44]
-rwxr-xr-x  1 user  staff    16K May 17 08:43 ./a.out

据我了解,代码没有变量,没有malloc和各种需要任何额外内存使用的语句,而不是代码本身,它将在[=39=时加载到内存中]宁。一些用于堆栈指针、帧指针等的额外内存是预期的,但不应太多。

有趣的是,当我运行代码的时候。 System Monitor给出了截然不同的意见。

所以我使用的是 MacOS,监视器显示虚拟内存使用量为 30Gb+

好吗?!也许这是由于一些优化,或者 MacOS 管理内存的一些独特技术。让我们在具有 1Gb 内存的 Ubuntu 虚拟机中尝试 运行ning。

我知道这看起来比 30Gb 更合理,但是 2356Kb?

我看错指标了吗?

As I understood, the code has no variable, no malloc and all kinds of statement that requires any additional memory usage other than the code itself, which will be loaded to the memory when running.

您的代码内容不多;但是您的代码通常与一些启动代码链接,这些启动代码执行预处理命令行参数、初始化 C 库的部分以及调用您的 main().

您还会有一个堆栈(例如,以便启动代码可以调用您的 main()),它会消耗内存(无论您是否使用它)。

当您的程序启动时,可执行加载程序还将“加载”(映射到您的虚拟地址 space)任何共享库(例如 C 标准库,启动代码可能需要它,而您并不需要)写,即使你自己不使用它)。

可能发生的另一件事是,当启动代码初始化 C 标准库时,C 标准库可以初始化堆(对于 malloc() 之类的东西),以及一些东西(C 标准的其余部分库初始化,启动代码的其余部分)可以使用 malloc(),即使您没有编写的代码不使用它。

当然操作systems/virtual内存管理使用页;所以每个程序部分的大小(.text.data 等)、每个共享库中的每个部分、堆栈、堆等;被四舍五入到页面大小。根据它是哪台计算机,页面大小可能为 4 KiB(最近的 ARM/M1 Apple 机器为 16 KiB);如果您未创建的启动代码需要 .data 部分中的 1 个字节,则它需要 4 KiB(或 16 KiB)的内存。

So I am using MacOS, the monitor states that the Virtual Memory usage is 30Gb+!

我猜大部分是 space 分配给堆的;其中使用了少量 space 而大多数未使用。如果您假设有 176 KiB 的私有内存(由您的程序及其启动代码使用)和 440 KiB 的共享内存(由共享库使用),并假设“32.54 GiB”为 3412000000 KiB;那么可能是“3412000000 - (176 + 440) = 3411999384 KiB of space 已分配但实际上未被使用”。

I know this looks more reasonable than 30Gb, but 2356Kb?

继续假设它主要是“已分配但未使用”堆 space;了解堆的工作原理是很好的。 “已分配但未使用”space 几乎没有成本,但要求 OS 分配 space(例如,因为程序实际上使用了它,并且 运行 出于“已分配但not used" space) 涉及一些开销。出于这个原因,C 库倾向于向 OS 请求大块“已分配但未使用”space(通过减少需要向 OS 请求的机会来最小化开销更多 space) 然后在调用 malloc().

时将其拆分成小块

考虑到这一点;并且不要忘记启动代码和库是“通用的”,不太可能专门针对任何一个程序进行优化;您可以说堆的“已分配但未使用”的最佳大小 space 无法确定,但是 运行 从“可能太小但无关紧要”到“可能太大”大但没人在乎”。不同的编译器 and/or 库 and/or 操作系统做出不同的决定;所以“已分配但未使用”的数量 space 有所不同。

Am I looking at the wrong indicator?

我不知道(这取决于您开始查看内存统计信息的原因)。

在现代机器上,总虚拟地址 space 可能是 131072 GiB(其中大部分是“未分配”),所以如果您担心“已分配但未使用”space会导致您 运行 脱离“未分配” space 之后您就会看到正确的指标。

但通常人们更关心“已分配和实际使用 space”(的某些子集)。

如果您担心消耗过多的实际 RAM(例如,担心 OS 使用交换 space 的机会增加,这可能会降低所有软件的性能,而不是只是你的)然后你想看看“实际内存大小”;但我怀疑这包括共享内存(许多程序会使用它,而不仅仅是你的程序)。