代码之家  ›  专栏  ›  技术社区  ›  KarlP

JVM垃圾收集和分页内存体系结构

  •  16
  • KarlP  · 技术社区  · 17 年前

    在最近10年中,当讨论java和/或垃圾收集时,我唯一无法辩护的性能损失是,垃圾收集算法在分页内存体系结构中运行时或多或少会中断,堆的一部分会被分页。

    我知道最好的做法是保持最大堆小于物理内存。(或者你会看到你的应用程序被交换到死地)但是这个想法——至少在unix世界中是这样的,内存可以更好地用于文件系统缓存等。

    我的问题是: 是否有任何分页(感知)垃圾收集算法?

    5 回复  |  直到 17 年前
        1
  •  9
  •   kdgregory    17 年前

    为了确保我们描述的是同一件事:一个完整的集合需要JVM遍历对象图以识别每个可访问的对象;剩下的是垃圾。在执行此操作时,它将触及应用程序堆中的每个页面,这将导致每个页面在被调出时出现内存故障。

    我认为这是一个不需要担心的问题,原因有几个:首先,因为现代JVM使用世代收集器,而且大多数对象永远不会离开年轻一代,而年轻一代几乎肯定会在常驻集中。

    其次,因为从年轻一代移出的对象仍然倾向于频繁访问,这也意味着它们应该在常驻集中。这是一个更为脆弱的论点,事实上,在很多情况下,长寿命的对象只有通过GC才会被触及(我不相信内存有限的缓存的一个原因)。

    第三个原因(可能还有更多)是因为JVM(至少是Sun JVM)使用了标记扫描压缩收集器。因此,在GC之后,堆中的活动对象占用的页面数量更少,这再次增加了RSS。顺便说一句,这是Swing应用程序在最小化时显式调用System.gc()的主要驱动因素:通过压缩堆,当它们再次被最大化时,交换的空间就更少了。


    另外,要认识到C/C++对象的堆碎片可能会变得极端,年轻的对象会分散在较老的对象中,因此RSS必须更大。

        2
  •  5
  •   Sebastien Loisel    15 年前

    您是正确的,垃圾收集器和虚拟内存管理器必须协作,否则GC将垃圾回收系统。Matthew Hertz、Yi Feng和Emery D.Berger对这种GC/内核协作进行了研究。为了获得良好的性能,他们必须稍微扩展内核,并调整垃圾收集器。

    在高内存压力下,使用GenMS Java GC,他们的基准测试花费了大约160倍的时间。使用新的、支持页面的GC,基准测试的速度只慢了1.6倍。换句话说,使用经过适当调整的GC,性能可以提高100倍。

    http://lambda-the-ultimate.org/node/2391

        3
  •  4
  •   Steve Jessop    17 年前

    我还要问一个反问题:是否有任何unix分页算法支持垃圾收集?如果一个给定的页面被定期(如果不是频繁的)拖到内存中,那么它可能毕竟不是一个很好的选择,而被抛弃以支持更多的磁盘缓存;-)

        4
  •  4
  •   John Feminella    17 年前

    Unix系统(尤其是Linux)会大量地分页出一段时间以来未被触及的内存,虽然这对一般泄漏的c应用程序有好处,但在内存紧张的情况下,它会扼杀Java的性能。

    a blog article I wrote on this 如果您想了解有关Linux上交换调优的更深入的信息。

    是否有任何分页(感知)垃圾收集算法?

    垃圾收集算法通常设计用于各种可能的程序作为输入,并在大量可能的环境中运行;他们的设计需要考虑到这一点。我认为制作一个广泛有用的“分页感知”gc算法将是一个挑战。如果你在为一个非常专业的环境写一篇文章,在这个环境中你可以锁定一些东西,那么我认为你有很好的机会产生一个好的结果。

        5
  •  0
  •   Tom Hawtin - tackline    17 年前

    在这个时代,分页程序是一个非常糟糕的主意。内存非常便宜。

    FWIW,如果你使用的是一家生产商生产的电脑,它喜欢为内存收取几倍的费用,那么Windows Vista有一种预测性分页算法,它工作得相当好(也许是操作系统唯一做得好的事情)。