Malloc vs自定义分配器:Malloc有很多开销。 为什么?

我有一个图像压缩应用程序,现在有两个不同版本的内存分配系统。 在原始版本中,malloc在任何地方都可以使用,而在第二个版本中,我实现了一个简单的pool-allocator,它只是分配大块内存并将该内存的一部分返回给myalloc()调用。

当使用malloc时,我们注意到一个巨大的内存开销:在内存使用的高度,malloc()代码需要大约170兆字节的内存用于1920x1080x16bpp的映像,而池分配器只分配48兆字节,其中47被程序使用。

就内存分配模式而言,该程序会在测试映像中分配大量8byte(大部分),32-byte(许多)和1080byte-blocks(部分)。 除此之外,代码中没有动态内存分配。

测试系统的操作系统是Windows 7(64位)。

我们如何测试内存使用情况?

使用自定义分配器,我们可以看到有多少内存被使用,因为所有malloc调用都被分配给了分配器。 使用malloc(),在调试模式下,我们只是遍历代码并观察任务管理器中的内存使用情况。 在发布模式中,我们做了同样的事情,但不太精细,因为编译器优化了很多东西,所以我们无法一步一步地完成代码(发行版和调试版之间的内存差异大约为20MB,我将其归因于在发布模式下优化和缺少调试信息)。

单靠malloc能成为这么大的开销的原因吗? 如果是这样,malloc里面的开销究竟是什么?


首先malloc将指针对齐到16个字节的边界。 此外,它们在返回值之前的地址中存储至少一个指针(或分配的长度)。 然后,他们可能会添加一个魔术值或释放计数器,以指示链表未被损坏或内存块未被释放两次(释放两次释放的ASSERTS)。

#include <stdlib.h>
#include <stdio.h>

int main(int ac, char**av)
{
  int *foo = malloc(4);
  int *bar = malloc(4);
  printf("%dn", (int)bar - (int)foo);
}

回报:32


在Windows 7上,您将始终得到低碎片堆分配器,而不显式调用HeapSetInformation()来请求它。 该分配器牺牲虚拟内存空间以减少碎片。 你的程序实际上并没有使用170兆字节,你只是看到一堆免费的块躺在周围,等待分配一个相似的大小。

这个算法容易被一个自定义分配器击败,它不会做任何事情来减少碎片。 这可能适合你,虽然你没有看到它的副作用,直到你保持程序的运行时间超过单个调试会话。 如果这是预期的使用模式,您需要确保它在几天或几周内保持稳定。

最好的事情就是不要担心,170 MB是相当小的土豆。 请记住,这是虚拟内存,它不需要任何费用。


警告:当您在Visual Studio中运行程序或连接了任何调试器时,默认情况下,malloc行为会发生很大变化,不会使用低碎片堆,内存开销可能不代表实际使用情况(另请参见https:/ /stackoverflow.com/a/3768820/16673)。 您需要使用环境变量_NO_DEBUG_HEAP = 1来避免被此命中,或者在未在调试器下运行时测量内存使用情况。

链接地址: http://www.djcxy.com/p/80437.html

上一篇: Malloc vs custom allocator: Malloc has a lot of overhead. Why?

下一篇: Custom implementation of malloc in C++