我想测试当我请求 24M 内存时操作系统分配了多少。
for (i = 0; i < 1024*1024; i++)
ptr = (char *)malloc(24);
当我这样写时,我从top
命令中得到 RES is 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;