考虑两个应用程序:多次调用malloc()的一个(num。1),以及调用malloc()几次的另一个(num。2)。 这两个应用程序都分配相同的内存量(假设为100MB)。
对于哪个应用程序,下一个malloc()调用会更快,#1或#2?
换句话说:malloc()是否有内存中分配位置的索引?最小化malloc()调用的数量可以提高性能?
回答
当然,这完全依赖于malloc的实现,但在这种情况下,如果没有调用free,大多数malloc实现可能会给你相同的算法速度。
作为另一个答案评论,通常会有一个空闲块列表,但如果你没有免费调用,只会有一个,所以它应该是O(1)在这两种情况下。
这假定在这两种情况下为堆分配的内存足够大。在#1的情况下,您将分配更多的总内存,因为每个分配涉及用于存储元数据的内存开销,因此您可能需要调用sbrk(),或者等价于在#1情况下增加堆,这会添加额外的开销。
由于缓存和其他二级效应,它们可能会有所不同,因为新分配的内存对齐方式不会相同。
如果你已经释放了一些内存块,那么由于较少的碎片以及更少的空闲块搜索列表,很可能#2会更快。
如果你已经释放了所有的内存块,它应该最终完全一样,因为任何理智的免费实现都会将块合并回单个内存区域。
这些当然是实现细节,但通常free()
会将内存插入到空闲块列表中。然后,malloc()
将查看此列表以查找空白大小合适或更大的空白块。通常,只有在这种情况下,malloc()
才会向内核请求更多的内存。
还有其他考虑因素,例如何时将多个相邻块合并为一个较大的块。
而另一个原因malloc()
是昂贵的:如果从多个线程调用malloc()
,这些全局结构必须有某种同步。 (即,锁)。存在具有不同优化方案的malloc()
实现,以使其更适合多线程,但通常,保持其多线程安全性会增加成本,因为多线程将争用这些锁并阻止彼此的进度。
答案是,它的大部分潜在缓慢来自malloc()和free()的组合,通常#1和#2将具有相似的速度。
所有malloc()实现都具有索引机制,但向索引添加新块的速度通常不取决于索引中已有块的数量。
大多数的malloc的缓慢的有两个来源
- 搜索所述以前释放(块)之间的一个合适的空闲块
- 多处理器问题锁定
写我拥有几乎符合标准的malloc()替换工具malloc()& & free()times 35%to 3-4%,并认真优化了这两个因素。使用其他一些高性能的malloc可能会有类似的速度,但是我们自己可以更容易地使用深奥的设备,当然也可以在某些地方自由地插入内存。
Malloc必须通过空闲块的链接列表才能找到要分配的块。这需要时间。因此,#1通常会比较慢:
越频繁调用malloc,更多的时间将需要 - 所以降低电话会给你一个速度的提升的数量(尽管无论是显著将取决于根据你的具体情况)。另外,如果malloc中有很多小块,那么当你释放这些块时,你将会比如果只分配并释放几个大块更多地分割堆。所以你可能最终会在你的堆上有许多小的空闲块,而不是几个大块,因此你的malloc可能不得不通过空闲空间列表进一步搜索以找到合适的块分配。这又会让他们变慢。
你问两个问题:
- 依据申请下一个的malloc()调用会更快,1号或2?
- 换句话说:malloc()是否有内存中分配位置的索引?
你已经暗示,他们是同样的问题,但事实并非如此。后一个问题的答案是YES。
至于哪个会更快,这是不可能的。它取决于分配器算法,机器状态,当前进程中的碎片等等。
但是,您的想法很有道理:您应该考虑malloc的使用情况如何影响性能。 曾经有一个我写的应用程序使用了很多小内存块,每个内存块都分配了malloc()。它工作正常,但速度很慢。我只用一个替换了malloc的很多调用,然后在我的应用程序中切分了大块。速度要快得多。
我不推荐这种方法;这只是一个例子,表明malloc的使用可以实质性地影响性能。
我的建议是测量它。
您没有定义“many”和“few”之间的相对差异,但我怀疑大多数malloc在两种情况下的功能几乎相同。这个问题意味着每次调用malloc都会有系统调用和页表更新的开销。当你进行malloc调用时,例如malloc(14)在一个非大脑死亡的环境中,malloc实际上会分配比你想要的更多的内存,通常是系统MMU页面大小的倍数。你得到你的14个字节,并且malloc跟踪新分配的区域,以便稍后的调用可以返回一块已经分配的内存,直到需要从操作系统请求更多的内存。
换句话说,如果我一次调用malloc(14)100次或malloc(1400),开销将大致相同。我只需要自己管理更大的分配内存块。
你可以总是使用malloc()分配一大块内存并自行细分它会做得更好。 Malloc()经过优化,可以在一般情况下运行良好,并且不会假设您是否使用线程或者程序的分配大小是多少。
实现自己的子分配器是个好主意是次要问题。很少情况下,显式内存管理已经够用了。你很少需要另一层代码,可以搞砸你的程序,没有任何好的方法来调试它。除非你正在编写调试分配器。
分配一块内存比分配多块更快。有系统调用的开销,也搜索可用的块。在编程中减少操作的次数通常会加快执行时间。
内存分配器可能必须搜索以找到正确大小的内存块。这增加了执行时间的开销。
但是,在分配小块内存与一个大块时,可能会有更好的成功机会。你的程序是分配一个小块并释放它,还是需要分配(并保留)小块。当内存变得碎片时,可用的块很少,所以内存分配器可能不得不合并所有块以形成足够大的分配块。
如果您的程序正在分配和销毁很多小块内存,您可能需要考虑分配一个静态数组并将其用于您的内存。
- 1. 并发性可以提高性能吗?
- 2. 哪种方法可以提高性能?
- 3. const-correctness可以提高性能吗?
- 4. 矢量化C++代码以提高STL性能
- 5. 提高微调器性能
- 6. 原型如何初始化实例变量可以提高性能
- 7. 提高异步Web调用的性能
- 8. Python - 以高性能序列化数据的最佳方式?
- 9. 优化性能,以最大像素值调整大小
- 10. 向量复制然后赋值可以提高性能
- 11. 将大型IIAF分割为更小的函数是否可以提高性能?
- 12. WPF VirtualizingStackPanel以提高性能
- 13. 数据库设计和性能:使用冗余FK提高性能可以吗?
- 14. 提高数据库可用性和性能的工作
- 15. 如何提高包含大量小图片的UCollectionView的性能?
- 16. 初始化可以找到最小数量的堆栈。 Java
- 17. 是否可以提高“最大永久磁盘数量”限制?
- 18. SQL Server中的不同用户可以帮助提高性能
- 19. C中的static关键字可以用来提高性能吗?
- 20. malloc/realloc /可用容量优化
- 21. 向量化切片的最小值和最大值可能吗?
- 22. 提高PHP图像上传/调整大小脚本的性能
- 23. java +提高性能和可伸缩性
- 24. 强类型数据集可以提高性能吗?
- 25. 分拆包含函数是否可以提高PHP性能?
- 26. 提高性能
- 27. 提高性能
- 28. 提高性能
- 29. 提高性能
- 30. 提高表变量删除的性能
它确实(有一个分配位置的索引) - “free”如何工作,但不需要使下一个'malloc'调用更小。如果其中一个程序已经分配并释放了很多并创建了碎片,那么这会使下一个'malloc'调用更慢,因为空闲列表将是一长串块,其中大部分块太小。 – 2010-01-16 22:38:33
一个观察结果是,一旦内存资源变得紧张,malloc处理较小的内存块可能是更好的方法。在这里或那里寻找一小块空闲的内存可能比较容易,而不是某处的巨块。不知道这将如何影响性能。 – 2010-01-16 22:38:49
malloc/free数据结构通常保留空闲块的链表,并且通常不会跟踪分配的块。它通常在头部预先分配数据。在免费它看起来在标题中找到分配的大小,然后将其添加到空闲块的链接列表。所以有一个空闲块的列表(但不是索引),除了程序员本身,没有任何记录分配块。 (当然,一个malloc实现可以做到这一点,它可能是一个很好的调试内存泄漏的方法。) – benno 2010-01-16 23:33:29