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



我有一个图像压缩应用程序,该应用程序现在具有两个不同版本的内存分配系统。在原始的中,Malloc在任何地方都使用,在第二个中,我实现了一个简单的池化属器,它只是将内存的一部分分配并将该内存的一部分返回到Myalloc(Myalloc()调用中。

使用Malloc时,我们一直在注意到一个巨大的内存开销:在其内存使用量的高峰时,Malloc()代码需要大约170兆字节的内存,用于1920x1080x16bpp的图像,而池分配仅分配48兆字节,该程序使用了47。

在内存分配模式方面,该程序分配了许多8字节(大多数),32字节(许多)和1080 byte-blocks(一些),并使用测试图像。除此之外,代码中没有动态内存分配。

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

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

使用自定义分配器,我们可以看到使用多少内存,因为将所有Malloc调用都递送给分配器。使用Malloc(),在调试模式下,我们刚刚浏览了代码,并在任务管理器中观看了内存使用量。在发布模式下,我们执行了相同的操作,但粒度不太细,因为编译器优化了很多东西,因此我们无法逐步浏览代码(发行和调试之间的内存差异约为20MB,我将其归因于在发布模式下优化和缺乏调试信息)。

单独的Malloc可能是造成如此巨大的开销的原因吗?如果是这样,是什么原因导致Malloc内部的开销?

在Windows 7上,您将始终始终获取低差异堆分配器,而无需明确调用HeapSetInformation()要求它。分配器牺牲虚拟记忆空间以减少碎裂。您的程序实际上不是使用170兆字节,您只是看到周围有很多自由块,等待分配相似的尺寸。

此算法是非常易于使用自定义分配器进行击败,该自定义分配器不做任何减少碎片的事情。这很可能对您有用,尽管您在保持程序的运行时间比单个调试会话更长之前不会看到它的副作用。如果这是预期的使用模式,您确实需要确保它稳定几天或几周。

最好的办法就是不烦恼它,170 MB是小土豆。并记住这是虚拟内存,它不会花费任何东西。

首先,所有malloc都将指针与16个字节边界保持一致。此外,他们在返回值之前的地址中将至少一个指针(或分配的长度)存储。然后,他们可能添加了一个魔术值或发行计数器,以表明链接列表没有被打破,或者尚未释放两次内存块(Double Frees的免费断言)。

#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

注意:当您在Visual Studio中运行程序或随附的任何调试器时,默认情况下,Malloc行为发生了很多更改,不使用低碎片堆,并且内存开销可能是不代表真实用法(另请参见https://stackoverflow.com/a/3768820/16673)。您需要使用环境变量_no_debug_heap = 1来避免被此击中,或者在不在调试器下运行时测量内存使用。

相关内容

  • 没有找到相关文章

最新更新