我想测试当我请求 24M 内存时操作系统分配了多少内存。
for (i = 0; i < 1024*1024; i++)
ptr = (char *)malloc(24);
当我这样写时,我从top
命令得到 RES 是 32M。
ptr = (char *)malloc(24*1024*1024);
但是当我做一点改变时,RES 是 244。它们之间有什么区别?为什么结果是244?
分配器有自己的关于簿记的数据结构,也需要内存。当您在小块中分配时(第一种情况),分配器必须保留大量有关每个块的分配位置和长度的额外数据。此外,您可能会在块之间获得未使用内存的间隙,因为malloc
需要返回一个足够对齐的块,通常是在 8 字节边界上。
在第二种情况下,分配器只给你一个连续的块,并且只对那个块进行簿记。
始终小心大量小分配,因为簿记内存开销甚至可能超过数据本身的数量。
第二个分配几乎不触及内存。分配器会告诉你"好吧,你可以拥有它",但如果你没有真正接触内存,操作系统永远不会真正给你它,希望你永远不会使用它。有点像庞氏骗局。另一方面,另一种方法将某些内容(最多几个字节)写入许多页面,因此操作系统被迫实际为您提供内存。
尝试这个来验证,你应该得到大约 24m 的使用:
memset(ptr, 1, 1024 * 1024 * 24);
简而言之,top 不会告诉您分配了多少,即您向malloc
提出了什么要求。它告诉您操作系统分配给进程的内容。
除了已经说过的内容:可能是一些编译器注意到你如何在循环中分配多个 24 字节块,将它们的地址分配给同一个指针,只保留你分配的最后一个块,有效地使之前的其他 malloc 无用。因此,它可能会将您的整个循环优化为如下所示:
ptr = (char *)malloc(24);
i = 1024*1024;