【问题标题】:Does JVM collection times increase exponentially with JVM RAM size?JVM 收集时间是否会随着 JVM RAM 大小呈指数增长?
【发布时间】:2018-02-14 04:49:09
【问题描述】:

我听到一位同事说:

JVM 垃圾收集时间随 JVM 大小呈指数增长。这是因为引用树是要分配的对象数量的函数 - 并且随着对象数量的增加,遍历树的难度呈指数增长。

这听起来不错。

我听到另一位同事说:

同一台机器上的 JVM 垃圾回收是线性的。假设将 8GB JVM 拆分为同一台机器上的两个 4G JVM(通过微服务)将具有相同的垃圾收集持续时间,因为相同的操作系统会为相同数量的对象减慢您的速度。

这似乎不对 - 因为两个较小的 JVM 上的对象树应该更浅且更易于遍历。

我的问题是:JVM 收集时间会随着 JVM RAM 大小呈指数增长吗?

假设:使用 Oracle JVM。

【问题讨论】:

    标签: performance garbage-collection jvm


    【解决方案1】:

    虽然 Holgers 的解释是正确的,但我想提出一个稍微不同的方面。 GC 花费的时间与活动集中的活动对象的数量成正比。这很容易证明。假设我们有两个具有相同大小的堆的应用程序。在第一个堆中,我们分配了 10 个每个 100 MB 的对象,在第二个堆中分配了 1000 万个,每个 100 字节。在下一次 gc 时,每个应用程序中的一半对象无法访问(死)并且可以被收集。

    不言而喻,要跟踪对象最多的图形需要更长的时间。

    (顺便说一句,我记得读过“浅而宽”与“深而窄”的测量结果,没有明显的区别,但我不记得在哪里。@Holger:如果你有一个来源,我很乐意阅读)

    请注意,遵循既定的 Java 编码实践实际上将确保活动集很小。 JVM 期望您以这种方式编写代码,并竭尽全力帮助保持较小的 live set,escape analysis 只是 Hot Spots 袖子的一个技巧。

    所以,简而言之:NO

    【讨论】:

    • 对于大物体的影响,可能有区别,e.g.通常不能包含对其他对象的引用的原始数组和引用类型的数组。但由于普通应用程序不会更改它们使用的数组类型,因此当可用内存量不同时,不会引入对堆大小的依赖...
    • 如果将压缩考虑在内,活动集大小的计算会变得更加棘手。标记只需要遍历引用并且可能会跳过大量数据。另一方面,复制需要移动所有的东西。
    • @the8472 压缩可能是一个问题,具体取决于收集器的类型。复制收集器在清理时会压缩内存区域。它也是收藏家中速度最快的。背面是内存要求。在 OpenJDK 中,它用于年轻一代。在老一代中,live set 在内存区域中移动,但移动一个大对象并不比一个小对象贵,反正都是 memcpy!
    【解决方案2】:

    没有这么简单的依赖。

    首先,将“垃圾收集”视为对象引用的函数显然只是指标记阶段,而忽略了分配、释放或复制/移动对象的成本。标记成本取决于必须遍历的 live 引用的数量,死对象或未使用的内存都不会对其产生任何影响。因此,仅仅为同一个应用程序提供更多 RAM 并不一定会改变垃圾收集性能。

    倾向于使用您为 JVM 提供的任意数量的 RAM,因此提供更多 RAM 可能会降低垃圾收集周期的频率,但可能需要更多时间来标记所有活动对象。但由于垃圾回收之间的间隔时间更长会增加对象未被使用的机会,因此标记成本通常不会与回收之间的时间相同。

    在实践中很容易证明它实际上是相反的。只需使用任意 Java 应用程序并将可用内存减少到它几乎不运行而不会遇到OutOfMemoryError 的程度。您将看到提供更少的 RAM 如何使其更慢,越接近该点,速度就越慢。另一方面,实际上没有必要证明为应用程序提供如此多的 RAM 以至于它在其生命周期内从不需要垃圾收集具有最小的成本。

    当我们只看标记阶段,而不考虑它发生的频率,而只考虑它如何随实时引用的数量而变化时,仍然没有理由认为它应该是指数级的。对象引用可以形成一个很少是树的任意图。此外,垃圾收集器不需要遍历每个对象引用。它只需要遍历它之前没有遇到过的对象的引用(猜猜为什么它被称为“标记”),这意味着需要遍历的引用数量与活动对象的数量相同。发现不需要遍历引用可能需要一些成本,但这仍然是线性开销。

    像 HotSpot(它不再是 Sun 的属性)这样的 JVM 使用分代垃圾收集和卡片标记,仅遍历内存部分(卡片)已更改的新对象和旧对象的引用,而不是所有活动对象。由于更改旧对象和创建新对象都需要 CPU 时间,因此它不能直接随可用 RAM 扩展。

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 1970-01-01
      • 2017-06-02
      • 2020-05-15
      • 2023-02-23
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      相关资源
      最近更新 更多