我已经在很多地方读取(赫克,我甚至写了那么我自己),垃圾回收可能(理论上)比手工内存管理更快。
但是,展示要比讲讲难得多。
我从未真正看到过任何代码可以证明这种效果。
是否有人拥有(或知道在哪里可以找到)证明这种性能优势的代码?
我已经在很多地方读取(赫克,我甚至写了那么我自己),垃圾回收可能(理论上)比手工内存管理更快。
但是,展示要比讲讲难得多。
我从未真正看到过任何代码可以证明这种效果。
是否有人拥有(或知道在哪里可以找到)证明这种性能优势的代码?
Answers:
请参阅http://blogs.msdn.com/b/ricom/archive/2005/05/10/416151.aspx,并通过所有链接查看Rico Mariani和Raymond Chen(微软的非常有能力的程序员)对决。雷蒙德将改进非托管服务器,雷科将通过优化托管服务器中的相同内容进行响应。
借助几乎为零的优化工作,托管版本的启动速度比手册快了很多倍。最终,手册击败了托管人员,但只能通过优化到大多数程序员都不想达到的水平。在所有版本中,该手册的内存使用情况均比托管版本好得多。
swap
)并不难,并且可能会很容易地使您达到性能方面的目标……
经验法则是没有免费的午餐。
GC消除了手动内存管理的麻烦,并减少了犯错误的可能性。在某些情况下,某些特定的GC策略是解决该问题的最佳解决方案,在这种情况下,您无需为此付出任何代价。但是在其他解决方案中,其他解决方案将更快。由于您始终可以从较低的级别模拟较高的抽象,但是不能反过来进行,因此可以有效地证明,在一般情况下,较高的抽象不可能比较低的抽象更快。
GC 是手动内存管理的特例
要手动获得更好的性能可能需要大量工作或更多错误,但这是另一回事。
容易构造一种人为的情况,在这种情况下,GC的效率要比手动方法高得多-只需安排垃圾收集器只有一个“根”,并且一切都是垃圾,因此GC步骤立即完成。
如果您考虑一下,那就是在垃圾回收分配给进程的内存时使用的模型。进程死了,它所有的内存都是垃圾,我们完成了。即使实际上,启动,运行和死亡的过程也不会留下任何痕迹,这比永久启动和运行的过程更有效率。
对于用带有垃圾回收的语言编写的实用程序,垃圾回收的优点不是速度而是正确和简单。
abort()
在程序退出之前用C ++ 调用一样。这是毫无意义的比较。您甚至没有进行垃圾收集,只是让内存泄漏。您不能说垃圾收集的速度更快(或更慢),如果您不是从一开始就进行垃圾收集……
我对此做了很多工作,并在此处进行了描述。我用C ++对Boehm GC进行了基准测试,使用malloc
但没有释放,使用分配和释放以及使用free
C ++编写的自定义标记区域GC进行分配,而OCaml的普通GC运行的是基于列表的n皇后求解器。在所有情况下,OCaml的GC都更快。故意编写C ++和OCaml程序以执行相同顺序的相同分配。
当然,您可以重写程序以仅使用64位整数而无需分配来解决问题。尽管速度更快,但会失败。(这是为了预测我正在使用C ++内置的原型在研究新的GC算法的性能)。
我在行业中花费了很多年,将真正的C ++代码移植到托管语言中。在几乎每种情况下,我都观察到性能上的实质性改进,其中许多可能是由于GC胜过了手动内存管理。实际的局限性不是可以在微基准测试中完成的,而是可以在截止日期之前完成的,而基于GC的语言可以极大地提高生产率,我从未回过头。我仍然在嵌入式设备(微控制器)上使用C和C ++,但即使现在这种情况也正在改变。
List.filter
像C ++一样使用自定义。但是,是的,您肯定可以取消某些RC操作。但是,我在野外看到的最大问题是,人们没有时间在大型工业代码库上手工执行这种优化。
shared_ptr
仅用于修复并发错误。代码慢了很多,但是,现在可以了。
这样的例子必然具有不良的手动存储器分配方案。
假设最好的垃圾收集器GC
。它在内部具有分配内存,确定可以释放哪些内存的方法以及最终释放内存的方法。这些在一起花费的时间比所有的时间少GC
; 在其他方法上花费了一些时间GC
。
现在考虑一个使用与相同的分配机制的手动分配器,该分配器GC
的free()
调用只是预留要通过与相同的方法释放的内存GC
。它没有扫描阶段,也没有任何其他方法。它必然需要更少的时间。
free
也可以收集批次。(当然,仅由于列表遍历本身,删除所有符合条件的项目仍然是O(N))
free
如果每个内存项都具有与之关联的标志,则可以在批处理模式下运行,尽管在某些情况下GC仍可以领先。如果一个人有N个引用,它们标识N个事物中的L个不同项,则删除不存在任何引用并合并其余部分的每个引用的时间为O(M)而不是O(N)。如果一个人有M个额外的可用空间,则缩放常数可能会很小。此外,在非扫描GC系统中进行压缩还需要...