JVM之Parallel Scavenge 收集器详解

前提提要

在pai中学到了Parallel Scavenge 收集器,说是吞吐量优先的收集器

内容如下:

所以我不由得好奇起了,他是做了哪些与Serial 收集器有所区分的设计,才能让他成为“吞吐量优先”

注释:这里的吞吐量指的是应用代码占用CPU核心的时间与总时间的比值

需要注意的是:不是特指单次,而是指总体来看

Parallel Scavenge 收集器

与 ParNew 一样是多线程收集器。

其它收集器关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而它的目标是达到一个可控制的吞吐量,它被称为“吞吐量优先”收集器。这里的吞吐量指 CPU 用于运行用户代码的时间占总时间的比值。

停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

缩短停顿时间是以牺牲吞吐量和新生代空间来换取的: 新生代空间变小,垃圾回收变得频繁,导致吞吐量下降。

可以通过一个开关参数打开 GC 自适应的调节策略(GC Ergonomics),就不需要手动指定新生代的大小(-Xmn)、Eden 和 Survivor 区的比例、晋升老年代对象年龄等细节参数了。虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。


著作权归@pdai所有 原文链接:https://pdai.tech/md/interview/x-interview.html

Parallel Scavenge做的特别设计

1. 并行化垃圾收集

Parallel Scavenge 使用多个线程并行执行垃圾收集工作,尤其是在新生代(Young Generation)进行的 Minor GC 中。通过并行执行垃圾收集,可以更快地完成垃圾收集任务,从而减少了应用程序因垃圾收集而停顿的总时间。

这里很好理解,吞吐量指的是应用代码占用CPU核心的时间与总时间的比值,那么另外的一部分时间肯定是用在垃圾清除上,所以是能提升吞吐量的

2. 默认启用的机制

  • 自适应调整策略(GC Ergonomics):这是 Parallel Scavenge 收集器的一个核心功能,默认情况下是启用的。它会根据应用程序的运行情况和系统负载,自动调整新生代和老年代的大小、Survivor 区的比例等参数,以优化性能和吞吐量。
  • 新生代大小的调整:Parallel Scavenge 收集器会动态调整新生代的大小,以减少 Minor GC 的频率,从而提高吞吐量。

这里由于自动调整新生代的大小,可能会导致下面提到的更长的停顿时间,那么更长的停顿时间又如何提升吞吐量呢?

3. 更长的停顿时间

为了提高吞吐量,Parallel Scavenge 收集器在设计上允许较长的停顿时间。这是因为它关注的是减少总的垃圾收集开销,而不是最小化每次垃圾收集的停顿时间。

到现在其实我们还没有推导出怎么提高吞吐量

深入复制算法

1. 减少指针重定位开销

每次垃圾收集涉及到对象的复制和指针更新。减少垃圾收集的次数可以减少总的指针重定位开销。

  • 固定开销
    • 每次垃圾收集都有固定的开销,如暂停应用程序线程、根集合扫描和数据结构更新。如果垃圾收集次数减少,这些固定开销的总和也会减少。
2. 内存分配效率

频繁的小批量对象复制会增加内存分配和管理的复杂度:

  • 分配指针管理
    • 在复制过程中,频繁的小批量复制会导致更多的分配指针管理操作。而一次性大批量复制则可以通过少量的指针管理操作完成大规模的内存分配。

深入操作系统

减少上下文切换和开销

  • 每次进行垃圾收集时,都会涉及到一些固定的开销,例如暂停应用程序线程、更新垃圾收集器的数据结构等。如果垃圾收集频率很高,这些固定开销的累积会显著增加总的垃圾收集时间。相反,减少垃圾收集的频率,即使每次停顿时间更长,也能减少这些固定开销的累积,从而提高吞吐量。

由此证明我们的Parallel Scavenge收集器是能够提升吞吐量的

posted @ 2024-06-17 22:42  海山了-  阅读(148)  评论(0编辑  收藏  举报