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

jef*_*yer 20 c++ garbage-collection raii

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

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

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

MSa*_*ers 12

从来没有,我可以证明这一点.

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

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

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

显然,?(?iTi) ? ?(Ti)有一种手动算法严格地不比GC算法差.

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

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

  • 你只是用你的数学解决释放(免费)问题.如何证明GC在整体上是劣等的? (3认同)
  • @MSalters:您在此处介绍的数学完全有缺陷,因为开始时的假设是不正确的。 (2认同)

Han*_*ant 11

GC优势:

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

GC缺点:

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

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

  • 你的结论充其量是误导性的.很少有Mariani/Chen的比较与内存管理有任何关系.那个小小的特别是因为当时的C++没有`move`构造函数(现在它).最后,任何知道自己在做什么的人都会编写类似于Raymond Chen的初始版本(或大多数中间步骤)的代码,这是值得怀疑的,除非作为一个稻草人后来敲门.最后,有问题的代码是一个足够古怪的任务,它是否真的对任何人都有意义是值得怀疑的. (6认同)
  • 除非使用Mark-Sweep-Compact算法(即MS .NET GC),否则GC不能简单地使用指针来分配内存.在非C++/CLR(即传统的C++)中,您将无法执行Compact部分. (3认同)
  • 好吧,这个答案与我的预期一样令人讨厌.你可以任意地将陈解雇为"糟糕的程序员",但这完全忽略了这一点.他最终*制作了一个击败Mariani版本的版本.关键在于他需要多个版本和数周才能到达那里.托管代码是一种生产力增强器,就是这样.至于C++在被困在泥泞中多年后获得移动语义,也许你应该考虑感谢强烈的竞争:) (3认同)