正如其他人正确指出的那样,很难掌握进程使用的实际内存,共享区域的内容,mmap文件和其他内容。
如果您是实验者,则可以运行valgrind和massif。对于临时用户而言,这可能会增加一些负担,但是您会逐渐了解应用程序的内存行为。如果应用程序malloc()恰好需要它,那么它将为您很好地表示进程的实际动态内存使用情况。但是这个实验可能会“中毒”。
使事情变得复杂的是,Linux允许您过量使用内存。当您使用malloc()内存时,就是在说明要消耗内存的意图。但是分配直到您将一个字节写入分配的“ RAM”的新页中才真正发生。您可以通过编写和运行一个如下的C程序来证明这一点:
// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
void *p;
sleep(5)
p = malloc(16ULL*1024*1024*1024);
printf("p = %p\n", p);
sleep(30);
return 0;
}
# Shell:
cc test.c -o test && ./test &
top -p $!
在内存少于16GB的计算机上运行此命令,瞧!您刚刚获得16GB的内存!(不,不是真的)。
请注意,top
您看到的“ VIRT”为16.004G,但%MEM为0.0
使用valgrind再次运行此命令:
# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30
而massif说“所有allocs()的总和= 16GB”。因此,这不是很有趣。
但是,如果您在合理的过程中运行它:
# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30
--------------------------------------------------------------------------------
Command: cc test.c -o test
Massif arguments: (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------
KB
77.33^ :
| #:
| :@::@:#:
| :::::@@::@:#:
| @:: :::@@::@:#:
| ::::@:: :::@@::@:#:
| ::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| @::@:::@:::::@:: :::@@::@:#:
| :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
| :@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| :::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
| ::::::::@::::@@:@@ :@::@:::@:::::@:: :::@@::@:#:
0 +----------------------------------------------------------------------->Mi
0 1.140
在这里(非常有经验并且非常有信心),我们看到编译器分配了77KB的堆。
为什么要这么努力才能获得堆使用率?因为进程使用的所有共享库和文本段(在此示例中为编译器)并不是很有趣。它们是流程的固定开销。实际上,该过程的后续调用几乎都是“免费”的。
此外,比较以下内容:
MMAP()1GB文件。您的VMSize将为1 + GB。但是,您的居民集大小将仅是导致分页的文件部分(通过取消引用指向该区域的指针)。而且,如果您“读取”整个文件,那么到结束时,内核可能已经分页了开头(这很容易做到,因为如果再次取消引用,内核确切地知道如何/在何处替换这些页面)。无论哪种情况,VMSize和RSS都不能很好地指示您的内存“使用情况”。您实际上并没有malloc()进行任何操作。
相比之下,Malloc()并触摸很多内存-直到您的内存被交换到磁盘上。因此,您分配的内存现在超过了RSS。在这里,您的VMSize可能会告诉您一些信息(您的进程拥有的内存比实际驻留在RAM中的内存更多)。但是,仍然很难区分共享页面的VM和交换数据的VM。
这就是valgrind / massif变得有趣的地方。它显示您有意分配的内容(无论页面状态如何)。
htop
笔者对前一天遇到的一个类似问题的答案... 如何从/ proc / meminfo(如htop)计算内存使用情况