量化垃圾收集与显式内存管理的性能

Emb*_*rog 19 c# c++ java memory garbage-collection

我在这里找到了这篇文章:

量化垃圾收集与显式内存管理的性能

http://www.cs.umass.edu/~emery/pubs/gcvsmalloc.pdf

在结论部分,它写道:

通过比较一系列基准测试的运行时,空间消耗和虚拟内存占用,我们表明,当给定足够的内存时,性能最佳的垃圾收集器的运行时性能与显式内存管理相比具有竞争力. 特别是,当垃圾收集的内存是所需内存的五倍时,其运行时性能与显式内存管理的性能相匹配或稍微超过.但是,当必须使用较小的堆时,垃圾收集的性能会大幅降低.内存的三倍,平均运行速度慢17%,内存增加一倍,运行速度减慢70%.当物理内存不足时,垃圾收集也更容易被分页.在这种情况下,我们在这里检查的所有垃圾收集器都会受到相对于显式内存管理的数量级性能损失.

所以,如果我的理解是正确的:如果我有一个用本机C++编写的应用程序需要100 MB内存,要实现与"托管"(即基于垃圾收集器)语言(例如Java,C#)相同的性能,应用程序应该要求5*100 MB = 500 MB?(并且2*100 MB = 200 MB,托管应用程序比本机应用程序运行速度慢70%?)

您是否知道当前(即最新的Java VM和.NET 4.0)垃圾收集器是否遇到上述文章中描述的相同问题?现代垃圾收集器的性能有所改善吗?

谢谢.

Mic*_*rdt 10

如果我有一个用本机C++编写需要100 MB内存的应用程序来实现与"托管"(即基于垃圾收集器的)语言(例如Java,C#)相同的性能,应用程序应该需要5*100 MB = 500 MB ?(并且2*100 MB = 200 MB,托管应用程序比本机应用程序运行速度慢70%?)

仅当应用程序在分配和释放内存时遇到瓶颈.请注意,该文件专门讨论了垃圾收集器本身的性能.

  • 对于上下文,我依赖OS或标准运行时分配器时,大部分大型实时应用程序花费了大约10-15%的时间来管理内存.我已经看到,当使用固定堆,块分配器,各种严格的优化时,这个数字下降到大约5%. (2认同)

Ste*_*n C 8

你似乎在问两件事:

  • 自从进行了研究以来,GC得到了改善
  • 我可以使用论文的结论作为预测所需记忆的公式.

第一个问题的答案是GC算法没有重大突破会使一般结论无效:

  • GC的内存管理仍然需要更多的虚拟内存.
  • 如果您尝试约束堆大小,GC性能会显着下降.
  • 如果实际内存受到限制,则由于分页开销,GC的内存管理方法会导致性能大大降低.

但是,结论不能真正用作公式:

  • 最初的研究是使用JikesRVM而不是Sun JVM完成的.
  • 自研究以来,Sun JVM的垃圾收集器在5年内得到了改进.
  • 该研究似乎没有考虑到Java数据结构比同等C++数据结构占用更多空间,原因与GC无关.

最后一点,我看过有人谈论Java内存开销的演讲.例如,它发现Java String的最小表示大小类似于48个字节.(一个String由两个原始对象组成;一个是一个具有4个字大小字段的对象,另一个是一个至少包含1个字的内容的数组.每个原始对象也有3或4个字的开销.)Java集合数据结构类似使用比人们意识到的更多的记忆.

这些开销本身与GC无关.相反,它们是Java语言,JVM和类库中设计决策的直接和间接后果.例如:

  • 每个Java原始对象标题1为对象的"标识哈希码"值保留一个字,并且为表示对象锁定保留一个或多个字.
  • 由于JVM的限制,String的表示必须使用单独的"字符数组".其他三个字段中的两个是尝试使substring操作减少内存密集.
  • Java集合类型使用大量内存,因为集合元素不能直接链接.因此,例如,Java中(假设的)单链接列表集合类的开销将是每个列表元素6个字.相反,最佳C/C++链表(即每个元素具有"下一个"指针)具有每个列表元素一个字的开销.

1 - 实际上,开销平均低于此.JVM仅在使用和争用后"膨胀"锁,并且类似的技巧用于身份哈希码.固定开销只有几位.然而,这些位累加到一个可测量的更大的对象标题......这是真正的要点.