HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

解析 JDK 7 的 Garbage-First 收集器

  • 2011-09-23
  • 本文字数:5137 字

    阅读完需:约 17 分钟

Garbage-First(后文简称 G1)收集器是当今收集器技术发展的最前沿成果,在 Sun 公司给出的 JDK RoadMap 里面,它被视作 JDK 7 的 HotSpot VM 的一项重要进化特征。从 JDK 6u14 中开始就有 Early Access 版本的 G1 收集器供开发人员实验、试用,虽然在 JDK 7 正式版发布时,G1 收集器仍然没有摆脱“Experimental”的标签,但是相信不久后将会有一个成熟的商用版本跟随某个 JDK 7 的更新包发布出来。

因版面篇幅限制,笔者行文过程中假设读者对 HotSpot 其他收集器(例如 CMS)及相关 JVM 内存模型已有基本的了解,涉及到基础概念时,没有再延伸介绍,读者可参考相关资料。

G1 收集器的特点

G1 是一款面向服务端应用的垃圾收集器,Sun(Oracle)赋予它的使命是(在比较长期的)未来可以替换掉 JDK 5 中发布的 CMS(Concurrent Mark Sweep)收集器,与其他 GC 收集器相比,G1 具备如下特点:

  • 并行与并发:G1 能充分利用多 CPU、多核环境下的硬件优势,使用多个 CPU(CPU 或者 CPU 核心)来缩短 Stop-The-World 停顿的时间,部分其他收集器原本需要停顿 Java 线程执行的 GC 动作,G1 收集器仍然可以通过并发的方式让 Java 程序继续执行。
  • 分代收集:与其他收集器一样,分代概念在 G1 中依然得以保留。虽然 G1 可以不需其他收集器配合就能独立管理整个 GC 堆,但它能够采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次 GC 的旧对象以获取更好的收集效果。
  • 空间整合:与 CMS 的“标记 - 清理”算法不同,G1 从整体看来是基于“标记 - 整理”算法实现的收集器,从局部(两个 Region 之间)上看是基于“复制”算法实现,无论如何,这两种算法都意味着 G1 运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次 GC。
  • 可预测的停顿:这是 G1 相对于 CMS 的另外一大优势,降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒,这几乎已经是实时 Java(RTSJ)的垃圾收集器特征了。

实现思路

在 G1 之前的其他收集器进行收集的范围都是整个新生代或者老年代,而 G1 不再是这样。使用 G1 收集器时,Java 堆的内存布局与就与其他收集器有很大差别,它将整个 Java 堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分 Region(不需要连续)的集合。

G1 收集器之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个 Java 堆中进行全区域的垃圾收集。G1 跟踪各个 Region 里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回价值最大的 Region(这也就是 Garbage-First 名称的来由)。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限的时间内获可以获取尽可能高的收集效率。

G1 把内存“化整为零”的思路,理解起来似乎很容易理解,但其中的实现细节却远远没有现象中简单,否则也不会从 04 年 Sun 实验室发表第一篇 G1 的论文拖至今将近 8 年时间都还没有开发出 G1 的商用版。笔者举个一个细节为例:把 Java 堆分为多个 Region 后,垃圾收集是否就真的能以 Region 为单位进行了?听起来顺理成章,再仔细想想就很容易发现问题所在:Region 不可能是孤立的。一个对象分配在某个 Region 中,它并非只能被本 Region 中的其他对象引用,而是可以与整个 Java 堆任意的对象发生引用关系。那在做可达性判定确定对象是否存活的时候,岂不是还得扫描整个 Java 堆才能保障准确性?这个问题其实并非在 G1 中才有,只是在 G1 中更加突出了而已。在以前的分代收集中,新生代的规模一般都比老年代要小许多,新生代的收集也比老年代要频繁许多,那回收新生代中的对象也面临过相同的问题,如果回收新生代时也不得不同时扫描老年代的话,Minor GC 的效率可能下降不少。。

在 G1 收集器中 Region 之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,虚拟机都是使用 Remembered Set 来避免全堆扫描的。G1 中每个 Region 都有一个与之对应的 Remembered Set,虚拟机发现程序在对 Reference 类型的数据进行写操作时,会产生一个 Write Barrier 暂时中断写操作,检查 Reference 引用的对象是否处于不同的 Region 之中(在分代的例子中就是检查引是否老年代中的对象引用了新生代中的对象),如果是,便通过 CardTable 把相关引用信息记录到被引用对象所属的 Region 的 Remembered Set 之中。当进行内存回收时,GC 根节点的枚举范围中加入 Remembered Set 即可保证不对全堆扫描也不会有遗漏。

运作过程

如果不计算维护 Remembered Set 的操作,G1 收集器的运作大致可划分为以下几个步骤:

  • 初始标记(Initial Marking)
  • 并发标记(Concurrent Marking)
  • 最终标记(Final Marking)
  • 筛选回收(Live Data Counting and Evacuation)

对 CMS 收集器运作过程熟悉的读者,一定已经发现 G1 的前几个步骤的运作过程和 CMS 有很多相似之处。初始标记阶段仅仅只是标记一下 GC Roots 能直接关联到的对象,并且修改 TAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的 Region 中创建新对象,这阶段需要停顿线程,但耗时很短。并发标记阶段是从 GC Root 开始对堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行。而最终标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程 Remembered Set Logs 里面,最终标记阶段需要把 Remembered Set Logs 的数据合并到 Remembered Set 中,这阶段需要停顿线程,但是可并行执行。最后筛选回收阶段首先对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来制定回收计划,从 Sun 透露出来的信息来看,这个阶段其实也可以做到与用户程序一起并发执行,但是因为只回收一部分 Region,时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。通过图 1 可以比较清楚地看到 G1 收集器的运作步骤中并发和需要停顿的阶段。

图 1 G1 收集器运行示意图

G1 收集器的实际性能

由于目前还没有成熟的版本,G1 收集器几乎可以说还没有经过实际应用的考验,网上关于 G1 收集器的性能测试非常贫乏,笔者没有 Google 到有关的生产环境下的性能测试报告。强调“生产环境下的测试报告”是因为对于垃圾收集器来说,仅仅通过简单的 Java 代码写个 Microbenchmark 程序来创建、移除 Java 对象,再用 -XX:+PrintGCDetails 等参数来查看 GC 日志是很难做到准衡量其性能的(为何 Microbenchmark 的测试结果不准确可参见笔者这篇博客: http://icyfenix.iteye.com/blog/1110279)。因此关于 G1 收集器的性能部分,笔者引用了 Sun 实验室的论文《Garbage-First Garbage Collection》其中一段测试数据,以及一段在 StackOverfall.com 上同行们对 G1 在真实生产环境下的性能分享讨论。

Sun 给出的 Benchmark 的执行硬件为 Sun V880 服务器(8×750MHz UltraSPARC III CPU、32G 内存、Solaris 10 操作系统)。执行软件有两个,分别为 SPECjbb(模拟商业数据库应用,堆中存活对象约为 165MB,结果反映吐量和最长事务处理时间)和 telco(模拟电话应答服务应用,堆中存活对象约为 100MB,结果反映系统能支持的最大吞吐量)。为了便于对比,还收集了一组使用 ParNew+CMS 收集器的测试数据。所有测试都配置为与 CPU 数量相同的 8 条 GC 线程。

在反应停顿时间的软实时目标(Soft Real-Time Goal)测试中,横向是两个测试软件的时间片段配置,单位是毫秒,以(X/Y)的形式表示,代表在 Y 毫秒内最大允许 GC 时间为 X 毫秒(对于 CMS 收集器,无法直接指定这个目标,通过调整分代大小的方式大致模拟)。纵向是两个软件在对应配置和不同的 Java 堆容量下的测试结果,V%、avgV% 和 wV% 分别代表的含义为:

  • V%:表示测试过程中,软实时目标失败的概率,软实时目标失败即某个时间片段中实际 GC 时间超过了允许的最大 GC 时间。
  • avgV%:表示在所有实际 GC 时间超标的时间片段里,实际 GC 时间超过最大 GC 时间的平均百分比(实际 GC 时间减去允许最大 GC 时间,再除以总时间片段)。
  • wV%:表示在测试结果最差的时间片段里,实际 GC 时间占用执行时间的百分比。

测试结果如下表所示:

表 1:软实时目标测试结果

Benchmark / confguration

Soft real-time goal compliance statistics by Heap Size

V%

avgV%

wV%

V%

avgV%

wV%

V%

avgV%

wV%

SPECjbb

512M

640M

768M

G1

(100/200)

4.29%

36.40%

100.00%

1.73%

12.83%

63.31%

1.68%

10.94%

69.67%

G1

(150/300)

1.20%

5.95%

15.29%

1.51%

4.01%

20.80%

1.78%

3.38%

8.96%

G1

(150/450)

1.63%

4.40%

14.32%

3.14%

2.34%

6.53%

1.23%

1.53%

3.28%

G1

(150/600)

2.63%

2.90%

5.38%

3.66%

2.45%

8.39%

2.09%

2.54%

8.65%

G1

(200/800)

0.00%

0.00%

0.00%

0.34%

0.72%

0.72%

0.00%

0.00%

0.00%

CMS

(150/450)

23.93%

82.14%

100.00%

13.44%

67.72%

100.00%

5.72%

28.19%

100.00%

Telco

384M

512M

640M

G1

(50/100)

0.34%

8.92%

35.48%

0.16%

9.09%

48.08%

0.11%

12.10%

38.57%

G1

(75/150)

0.08%

11.90%

19.99%

0.08%

5.60%

7.47%

0.19%

3.81%

9.15%

G1

(75/225)

0.44%

2.90%

10.45%

0.15%

3.31%

3.74%

0.50%

1.04%

2.07%

G1

(75/300)

0.65%

2.55%

8.76%

0.42%

0.57%

1.07%

0.63%

1.07%

2.91%

G1

(100/400)

0.57%

1.79%

6.04%

0.29%

0.37%

0.54%

0.44%

1.52%

2.73%

CMS

(75/225)

0.78%

35.05%

100.00%

0.54%

32.83%

100.00%

0.60%

26.39%

100.00%

从上面结果可见,对于 telco 来说,软实时目标失败的概率控制在 0.5%~0.7% 之间,SPECjbb 就要差一些,但也控制在 2%~5% 之间,概率随着(X/Y)的比值减小而增加。另一方面,失败时超出允许 GC 时间的比值随着总时间片段增加而变小(分母变大了嘛),在(100/200)、512MB 的配置下,G1 收集器出现了某些时间片段下 100% 时间在进行 GC 的最坏情况。而相比之下,CMS 收集器的测试结果对比之下就要差很多,3 种 Java 堆容量下都出现了 100% 时间进行 GC 的情况,

在吞吐量测试中,测试数据取 3 次 SPECjbb 和 15 次 telco 的平均结果。在 SPECjbb 的应用下,各种配置下的 G1 收集器表现出了一致的行为,吞吐量看起来只与允许最大 GC 时间成正比关系,而在 telco 的应用中,不同配置对吞吐量的影响则显得很微弱。与 CMS 收集器的吞吐量对比可以看到,在 SPECjbb 测试中,在堆容量超过 768M 时,CMS 收集器有 5%~10% 的优势,而在 telco 测试中 CMS 的优势则要小一些,只有 3%~4% 左右。

图 2:吞吐量测试结果

在更大规模的生产环境下,笔者引用一段在 StackOverfall.com 上看到的经验分享:“我在一个真实的、较大规模的应用程序中使用过 G1:大约分配有 60~70GB 内存,存活对象大约在 20~50GB 之间。服务器运行 Linux 操作系统,JDK 版本为 6u22。G1 与 PS/PS Old 相比,最大的好处是停顿时间更加可控、可预测,如果我在 PS 中设置一个很低的最大允许 GC 时间,譬如期望 50 毫秒内完成 GC(-XX:MaxGCPauseMillis=50),但在 65GB 的 Java 堆下有可能得到的直接结果是一次长达 30 秒至 2 分钟的漫长的 Stop-The-World 过程;而 G1 与 CMS 相比,它们都立足于低停顿时间,CMS 仍然是我现在的选择,但是随着 Oracle 对 G1 的持续改进,我相信 G1 会是最终的胜利者。如果你现在采用的收集器没有出现问题,那就没有任何理由现在去选择 G1,如果你的应用追求低停顿,那 G1 现在已经可以作为一个可尝试的选择,如果你的应用追求吞吐量,那 G1 并不会为你带来什么特别的好处。”

在这节笔者引了两段别人的测试结果、经验后,对于 G1 给出一个自己的建议:直到现在为止还没有一款“最好的”收集器出现,更加没有“万能的”收集器,所以我们选择的只是对具体应用最合适的收集器。对于不同的硬件环境、不同的软件应用、不同的参数配置、不同的调优目标都会对调优时的收集器选择产生影响,选择适合的收集器,除了理论和别人的数据经验作为指导外,最终还是应当建立在自己应用的实际测试之上,别人的测试,大可抱着“至于你信不信,反正我自己没测之前是不信的”的态度。

参考资料


感谢张凯峰对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家加入到 InfoQ 中文站用户讨论组中与我们的编辑和其他读者朋友交流。

2011-09-23 00:0011713

评论

发布
暂无评论
发现更多内容

iPaaS 平台的发展方向

RestCloud

数字化转型 数据集成平台 企业集成 ipaas

Cornerstone for Mac(SVN管理工具)v4.2激活版

Mac相关知识分享

面试官:Java中缓冲流真的性能很好吗?我看未必

EquatorCoco

Java 面试 程序员面试 开发语言

华为大咖说 | 数字时代的财富秘诀:数据资产化全攻略

华为云PaaS服务小智

华为云 资产管理

测试工程师在敏捷项目中扮演什么角色?

禅道项目管理

敏捷开发 软件测试 软件开发 迭代 测试人员

Beyond Compare 4 文件同步对比工具|适用于PC端和macOS电脑

理理

VSD Viewer破解版(Visio绘图文件阅读器) v6.16.1激活版

理理

生产环境Nginx配置

源字节1号

小程序 开源 前端 后端

借助 API 接口深挖 1688 商品详情的奥秘

Noah

理解 gRPC 与 REST:选择适合您项目的最佳 API 方案

Liam

程序员 gRPC 后端 Rest API

工时记录软件:节省时间和金钱的最佳选择

爱吃小舅的鱼

工时管理 工时管理系统

Deckset for Mac(MD文档转幻灯片软件) v2.0.33激活版

Mac相关知识分享

FonePaw Video Converter Ultimate for mac(视频格式转换软件)激活版

Mac相关知识分享

Ceph PG状态介绍

天翼云开发者社区

分布式 存储 Ceph

腾讯云大数据连续三年蝉联中国大数据市场领导者象限

腾讯云大数据

腾讯云 大数据

(2024最新)Pycharm破解激活2099年激活码教程(含win+mac)

理理

set a light 3d studio 2.5汉化版 Mac 3D模拟布光软件

理理

手把手教你搭建Docker私有仓库Harbor

不在线第一只蜗牛

Docker 容器 仓库

云容灾关键技术点简介

天翼云开发者社区

云计算 云服务 容灾备份

Bonree ONE赋能汽车行业 重塑可观测性体验

博睿数据

(永久激活)MAMP PRO 本地Web服务器开发环境 【Mac/win】

理理

TDengine 3.3.2.0 发布:新增 UDT 及 Oracle、SQL Server 数据接入

TDengine

ISA-L库调研

天翼云开发者社区

大数据 存储 simd

快照技术对比学习

天翼云开发者社区

云计算 快照技术

SD-WAN为什么成为小企业的首选

Ogcloud

SD-WAN 企业组网 SD-WAN组网 SD-WAN服务商 SDWAN

PDF Expert for mac(pdf编辑工具) v3.8.2中文激活版

Mac相关知识分享

淘宝店铺商品搜索API返回值全面解析:洞悉店铺全貌

技术冰糖葫芦

API API 编排 API 文档 API 协议

photoshop2020电脑配置要求 ps 2020中文直装版下载【Mac/win】

理理

多项第一!天翼云霸气登顶政务公有云市场

Geek_2d6073

喜讯!云起无垠入选《2024年中国网络安全市场全景图》

云起无垠

RTX 4090为什么被称为性能之王?

Finovy Cloud

显卡 显卡选择 #GPU

解析JDK 7的Garbage-First收集器_Java_周志明_InfoQ精选文章