OpenJDK 8具有几种垃圾收集器算法,例如Parallel GC , CMS和G1 。 哪一个最快? 如果默认的GC从Java 8中的并行GC更改为Java 9中的G1(当前建议),将会发生什么? 让我们对其进行基准测试。
基准方法
- 使用不同的VM参数运行相同的代码6次(
-XX:+UseSerialGC
,-XX:+UseParallelGC
,-XX:+UseConcMarkSweepGC
,-XX:ParallelCMSThreads=2
,-XX:ParallelCMSThreads=4
,-XX:+UseG1GC
) 。 - 每次运行大约需要55分钟。
- 其他VM参数:
-Xmx2048M -server
OpenJDK版本:1.8.0_51
(当前最新版本)
软体:Linux version 4.0.4-301.fc22.x86_64
硬件:Intel® Core™ i7-4790 CPU @ 3.60GHz
- 每次运行都能使用OptaPlanner解决13个计划问题。 每个计划问题要运行5分钟。 它以30秒的JVM预热开始,该预热将被丢弃。
- 解决计划问题不涉及任何IO (启动期间要加载输入的时间只有几毫秒)。 一个CPU完全饱和。 它会不断创建许多短命的对象,然后GC会收集它们。
- 基准衡量每毫秒可以计算的分数数量。 越高越好。 为拟议的规划解决方案计算分数并非易事:涉及许多计算,包括检查每个实体与每个其他实体之间的冲突。
要在本地重现这些基准, 请从源代码构建optaplanner并运行主类GeneralOptaPlannerBenchmarkApp 。
基准结果
执行摘要
为了方便起见,我将每种垃圾收集器类型与Java 8(并行GC)中的默认类型进行了比较。
结果很明显: 该默认值(并行GC)是最快的。
原始基准数字
相对基准数字
Java 9是否应该默认为G1?
有建议使G1在服务器的OpenJDK9中成为默认的垃圾收集器 。 我的第一反应是拒绝这个提议 :
- G1平均为
17.60%
。 - 对于每个数据集,每个用例的G1始终较慢。
- 在最大数据集(Machine Reassignment B10)上,它使任何其他数据集的大小都
34.07%
,, G1为34.07%
较慢。 - 如果开发人员机器和服务器之间的默认GC不同,则开发人员基准测试的可信度将降低。
另一方面,需要注意一些细微差别:
- G1专注于限制GC暂停,而不是吞吐量。 对于这些用例(计算量很大),GC暂停长度基本上无关紧要。
- 这是(几乎)单线程基准。 在并行或多线程求解中使用多个求解器进行进一步的基准测试可能会影响结果。
- 建议使用G1的堆大小至少为
6 GB
。 该基准测试仅使用了2 GB
的堆大小,甚至只有最大的数据集(Machine Reassignment B10)才需要该大小。
繁琐的计算只是OpenJDK所使用的众多功能之一:在整个社区辩论中,它只是利益相关者中的一员。 如果其他利益相关者(例如Web服务)证明相反,则值得更改默认GC。 但是,请先向我展示真实项目的基准 !
结论
在Java 8中,默认的垃圾收集器(Parallel GC)通常是OptaPlanner用例的最佳选择。
翻译自: https://www.javacodegeeks.com/2015/08/what-is-the-fastest-garbage-collector-in-java-8.html