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

Tra*_*isG 10 c memory malloc

我有一个图像压缩应用程序,现在有两个不同版本的内存分配系统.在最初的一个中,malloc在任何地方使用,在第二个中,我实现了一个简单的池分配器,它只分配一块内存并将部分内存返回给myalloc()调用.

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

在内存分配模式方面,程序为测试映像分配了大量8字节(大多数),32字节(许多)和1080字节块(一些).除此之外,代码中没有动态内存分配.

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

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

使用自定义分配器,我们可以看到使用了多少内存,因为所有malloc调用都被赋予分配器.使用malloc(),在调试模式下,我们只需逐步执行代码并在任务管理器中查看内存使用情况.在发布模式下我们也做了同样的事情,但由于编译器优化了很多东西,所以我们无法逐步完成代码(发布和调试之间的内存差异大约为20MB,我将其归因于在发布模式下优化和缺少调试信息).

可以单独使用malloc是导致如此巨大开销的原因吗?如果是这样,究竟是什么原因导致malloc内部的开销?

Han*_*ant 8

在Windows 7上,您将始终获得低碎片堆分配器,而无需显式调用HeapSetInformation()来请求它.该分配器牺牲了虚拟内存空间以减少碎片.你的程序实际上并没有使用170兆字节,你只是看到一堆闲置块在等待分配类似的大小.

这个算法非常容易被自定义分配器击败,它不会做任何事情来减少碎片.这对您来说可能很有用,尽管在程序运行时间超过单个调试会话之前,您没有看到它的副作用.如果这是预期的使用模式,您需要确保它稳定数天或数周.

最好的办法就是不要担心,170 MB是相当小的土豆.并且请记住,这是虚拟内存,它不需要任何费用.

  • “在 Windows 7 上,您将始终获得低碎片堆分配器”您会的,除非您在调试器下运行。根据所描述的方法(单步执行代码),在测量内存消耗时似乎使用了调试器,因此未使用 LFH。看我的回答。 (2认同)

Aki*_*nen 5

首先,malloc将指针对齐到16字节边界.此外,它们在返回值之前的地址中存储至少一个指针(或分配的长度).然后他们可能会添加一个魔术值或释放计数器来指示链接列表没有被破坏或者内存块没有被释放两次(免费ASSERTS用于双重释放).

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

int main(int ac, char**av)
{
  int *foo = malloc(4);
  int *bar = malloc(4);
  printf("%d\n", (int)bar - (int)foo);
}
Run Code Online (Sandbox Code Playgroud)

回程:32

  • @UmNyobe:显然是我的错.无论如何,8字节malloc占用32个字节,**32字节**malloc占用至少48个字节. (2认同)