G1,CMS及PARALLEL GC的比较
这篇文章正好接上前一年我们做的一次现实环境下不同GC算法性能比较的试验。这次我们仍然进行同样的试验,不过增加了对G1回收器的测试,并且在多个平台进行测试。今年我们测试的垃圾回收器有如下几个:
- -XX:+UseParallelOldGC
- -XX:+UseConcMarkSweepGC
- -XX:+UseG1GC
运行环境
我们使用现成的 JIRA任务来运行这个测试。选择它的原因非常简单——除去Minecraft(一款著名网游),愤怒的小鸟,以及Eclipse不说, JIRA应该是最著名的Java应用程序了。并且和别的候选者相比,它更能代表我们日常的业务处理流程——毕竟来说Java用得最多的地方还是在服务端的Java企业级应用。
影响我们决定的还有一个因素—— Atlassian的工程师们发布了一个打包好的JIRA压测脚本 。我们可以直接用它来进行我们的基准测试。
我们仔细的将最新版的JIRA6.1解压,然后把它安装到Mac OS X Mavericks上。最后直接使用默认的内存参数设置来运行这个测试程序。Atlassian团队的家伙已经帮我们把参数也设置好了:
-Xms256m -Xmx768m -XX:MaxPermSize=256m
这个程序使用了JIRA的常见的几种不同功能——创建任务,分配任务,解析任务,查找及发现任务,等等。总的运行时间是30分钟。
我们使用了三种不同的GC算法来运行这个测试——Parallel,CMS, 和G1。每次测试都重新启动一个新的JVM实例,并事先把存储恢复到同样的状态。一切准备就绪后我们才开始启动压测。
结果
每次测试我们都通过-XX:+PrintGCTimeStamps -Xloggc:/tmp/gc.log -XX:+PrintGCDetails来收集GC日志,最后使用GCViewer来分析里面的数据。
汇总后的结果如下。注意测试结果的单位是毫秒。
年 | Parallel | CMS | G1 |
Total GC pauses | 20 930 | 18 870 | 62 000 |
Max GC pause | 721 | 64 | 50 |
说明
首先来看Parallel GC (-XX:+UseParallelOldGC)。在这30分钟的测试过程中,并行收集器的GC大概暂停了有21秒。最长的一次花了721毫秒。我们来以这个做为基准:从总的运行时间来看,GC周期减少了1.1%的吞吐量。最长的延迟时间大概是721毫秒。
下一个:CMS(-XX:+UseConcMarkSweepGC)。在30分钟的测试中,由于GC而损失的时间是19秒。吞吐量和上一次的并行模式下的差不多。不过时延方面有了明显的改善——最坏的情况下的时延减少了10倍!现在最大的GC暂停时间只有64毫秒。
最后一次测试用的是最新最潮的GC算法——GC(-XX:+UseG1GC)。运行的是同样的测试程序,不过结果的吞吐量则严重下降了。这次测试应用在GC上花费的时间超过了一分钟。和CMS只有1%的开销相比,这次的吞吐量下降了有3.5%。不过如果你不在乎吞吐量而更在乎时延的话——这方面它和前面表现最好的CMS相比还有20%的提升——G1回收器最长的暂停时间只有50ms。
结论
想通过这么一次试验来得出一个结论是非常危险的。如果你的时间充足又有相应的能力的话——你应该在自己的环境中具体情况具体分析,而不是使用一刀切的方法。
不过如果说非要得出一个结论,我认为说CMS仍然是最佳的默认选择。G1的吞吐量实在是太差,和它所减少的那点时延相比并不划算。
原创文章转载请注明出处: G1,CMS及PARALLEL GC的比较