什么时候垃圾收集比手动内存管理更快?

时间:2011-08-08 01:14:33

标签: c++ garbage-collection raii

在什么情况下垃圾收集比手动内存管理更有效? (这里的手册可能意味着在C中使用malloc和free,或者使用C ++推广的更清晰的RAII和智能指针技术)

我喜欢垃圾收集如何从编写软件中消除一些偶然的复杂性,但我更加高兴的是RAII和智能指针如何消除这种复杂性,同时还可以处理除内存以外的资源,确定性,并提供性能保证和整体效率更高。所以我想我可以安全地忽略垃圾收集。但是,我注意到人们一直在说垃圾收集比C ++中使用的紧密资源管理更快,例如当有大量额外内存可用时。

那么什么时候垃圾收集完全可以胜过手动内存管理?我喜欢RAII和智能指针,但如果速度更快,很乐意接受垃圾收集作为另一种工具。

3 个答案:

答案 0 :(得分:13)

从不,我可以证明这一点。

首先,让我们假设我们在任何一种情况下都使用最好的算法。使用次优算法可以证明什么。

其次,让我们假设最好的GC算法使用时间T0...Tn来决定是否应该在某个时刻释放内存分配i。总数为Σ(Ti)

现在,存在使用相同GC算法的等效手动内存管理算法,但仅考虑已手动标记为已释放的内存块。因此,运行时间为Σ(δiTi)(当块i未被释放时δi= 0,当它被释放时为= 1)。

显然,Σ(δiTi) ≤ Σ(Ti):有一种手动算法,严格来说不比GC算法差。

这与其他答案形成鲜明对比?

  • “使用RAII,您必须在每次分配时解除分配。” - 不,这是一个错误的假设。我们应该比较批量或非批量操作。如果你在每次超出范围时也进行GC运行,GC会更糟糕。
  • “改进的地方性” - 好吧,除非你忽略了非GC语言可以更频繁地使用堆栈的事实,并且该堆栈具有极佳的引用位置。
  • “漏洞率低” - 这完全正确,但我们正在讨论运行时性能。 (顺便说一句:很好地指出它很低但非零赔率)。

答案 1 :(得分:11)

GC的优势:

  • 一个GC只是通过递增指针来分配,堆分配器必须采取反措施来避免堆碎片
  • GC改善了cpu缓存局部性,这对现代处理器来说很重要
  • GC不需要额外的代码来释放内存,泄漏的可能性很小
  • 一代GG可以同时收集垃圾,使内存管理在多核CPU上接近免费。

GC缺点:

  • 难以在将指针视为头等类型的语言中提高效率
  • 由于收集延迟而使用更多虚拟内存空间
  • 内存以外的操作系统资源的泄漏抽象
  • 在收集垃圾的情况下,
  • 在某些情况下会导致程序操作暂停。

对于perf来说,这是一个灌篮,GC不费力地轻松击败堆分配器。 Rico Mariani和Raymond Chen之间的汉语词典编程比赛经常被引用,概述is here。雷蒙德的C ++程序最终赢了,但只是在重写了几次并放弃了标准的C ++库之后。

答案 2 :(得分:2)

我知道有一个特殊的场景,当GC指针比传统的C ++(即不是C ++ / CLR,而不是C ++ / CLR)实现时,GC指针比智能指针(引用计数指针)要快得多。 Mark-Sweep之后的内存,我们正试图在这里尽可能多地比较苹果和苹果)假设GC使用相同的底层堆内存管理器。当你的对象分配时间明显超过对象创建时间时。

示例包括排序,数组反转等。

请参阅此处查看more info on my test with a GC framework I implemented using traditional C++ vs引用计数指针。阵列反转测试的结果是GcString比ref count String快16.5倍。

这可能归因于引用计数指针中缓慢的总线锁定语义(除非您的目标是纯单线程应用程序,因此线程安全需要锁定)。根据我在传统C ++中实现高性能精确GC的经验,我可以说使用GC vs 'manual'(根据OP的手册定义)内存管理(即ie)有更多机会进行优化智能指针)。