一次JVM内存调优的分享
这篇文章是关于最近一次性能调优的经历。跟往常一样,开始的时候总会有一些模糊的征兆。这次的现象看起来是”应用程序运行缓慢,但是我们无法获取到对应的源代码。我们该如何来解决这个问题“。
仔细观察下这个应用会发现它运行着一些批量任务。分析下性能相关的指标会发现它在运行某个特定任务的时候花费的时间太长了。进一步分析我得出了一个可量化的优化目标。我需要将这个任务预分配内存所占用的时间减少两分钟。
这个出问题的应用程序只是个非常无辜的小jar包而已。幸运的是,我对它进行了压测。
打开GC日志开关(-XX:+PrintGCTimeStamps -Xloggc:/path-to/gc.log -XX:+PrintGCDetails)后运行这个应用程序,并分析日志,很快你就会发现第一个要优化的目标。GC暂停时间加起来花了有3分半钟,这说明这块是一个优化的机会。
像这种情况一般有好几种解决办法 ,下面几种是比较简单和直接的:
- 修改堆的大小
- 调整GC算法
- 调整内存堆各区域的大小比例。
我选择了修改堆大小的方式。这并不是我运气好而蒙对的,是因为我最近学习了一些关于存活数据集大小和推荐的堆大小关系的东西。从GC日志中我注意到存活数据集大概是240M。因此根据我最近所了解到的知识来看,应用的最佳堆大小大概是在720M到960M之间。
不过我发现现在配置的堆大小只有300M。调整了下参数后我重新运行了下该测试用例 ,结果如下:
堆大小 | 总的GC暂停时间 | 吞吐量 |
300m | 207.48s | 92.25% |
384m | 54.13s | 97.97% |
720m | 20.52s | 99.11% |
1,440m | *11.37s | *99.55% |
*号表示没有出现Full GC。
如果你光看这个结果的话可能会认为结论是” 越大越好“。如果你只看这个毫秒值的话,你这么想也是对的。但如果成功的指标中有一项是和钱有关的话,就不那么容易了。成百上千台机器上进行大规模部署的话,你这么搞 ,到时光电费单就能吓你一跳。
除此之外,这篇文章也是性能调优课程上的一个用例。如果你有一个可测量的目标并且你可以去测量它的结果而不是去猜测,那么你就已经成功了。如果我没有一个明确的目标或者没法进行压测的话,可能我现在还在东调整下西调整下那么瞎捣鼓。
原创文章转载请注明出处: 一次JVM内存调优的分享