虚拟机内存问题和Java虚拟机优化案例分析

发布时间:2021-06-29 09:28:30 作者:chen
来源:亿速云 阅读:158

这篇文章主要讲解了“虚拟机内存问题和Java虚拟机优化案例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“虚拟机内存问题和Java虚拟机优化案例分析”吧!

问题总结

  1. 内存多占1G左右,CPU利用率没有明显变化,但随着CMS收集抖动,最高达40%,CPU load平均高出1.0左右

  2. 几乎0停顿,相比于之前每隔5分钟应用停顿3-4s,调优后的应用几乎没有停顿时间,每次”stop the world” 由 youngGC 引起,最高也不过200+ms

  3. GC总时间开销显著减小20%多,吞吐量显著提升

  4. 应用超过500ms的请求响应时间减少3%

参数对比

调优前

-Dfile.encoding=UTF-8 -server -Xms8000M -Xmx8000M -Xmn5000M -Xss256K - 
XX:ThreadStackSize=256 -XX:StackShadowPages=8  -verbose:gc -XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseParallelGC

调优后

-Dfile.encoding=UTF-8 -server -Xms10000M -Xmx10000M -Xmn5000M -
XX:MaxTenuringThreshold=1 -XX:SurvivorRatio=30 -XX:TargetSurvivorRatio=50 
-Xnoclassgc -Xss256K -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:PermSize=256m -
XX:MaxPermSize=256m  -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -
XX:CMSInitiatingOccupancyFraction=80  -XX:ParallelGCThreads=24  -XX:ConcGCThreads=24 
-XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark 
-XX:+ExplicitGCInvokesConcurrent -XX:+UseTLAB  -XX:TLABSize=64K

经验分享

在开始前,我们需要一些数据,因为jvm调优没有一个标准的答案,根据实际应用不同而不同,但也不是完全没有章法可言,从一个实际的应用,我们也可以找出一些规律来,找出一些比较公用的,比如下面三条:

  1. 应用平均和最大暂停时间(stop the world)

  2. 吞吐量,真正运行时间/(GC时间+真正运行时间),而相对的GC开销为:GC时间/(GC时间+真正运行时间)

  3. URL的请求响应时间

查看可以设置的所有参数

使用 -XX:+PrintFlagsFinal 参数:可以查看当前版本的虚拟机所能设置的所有参数,还可以看到其默认值。我使用6u26版本的java虚拟机,一共有663个参数,很多参数不必完全搞懂什么意思,而且很多优化项在JDK6版本中已经默认开启,所以我们只需要了解一些常用的即可。

最大堆的设置

GC策略的选择

虚拟机内存问题和Java虚拟机优化案例分析

初始标记(stop the world)

1093.220: [GC [1 CMS-initial-mark: 4113308K(5120000K)] 4180786K(10080000K), 0.0732930 
secs] [Times: user=0.07 sys=0.00, real=0.07 secs]

运行时标记(并发)

1094.275: [CMS-concurrent-mark: 0.980/0.980 secs]
[Times: user=19.95 sys=0.51, real=0.98 secs]

运行时清理(并发)

1094.305: [CMS-concurrent-preclean: 0.028/0.029 secs] 
[Times: user=0.10 sys=0.02, real=0.03 secs]

CMS: abort preclean due to time 1099.643:
[CMS-concurrent-abortable-preclean: 5.288/5.337 secs] 
[Times: user=12.64 sys=1.19, real=5.34 secs]

重新标记(stop the world,这个例子remark前执行了一次youngGC)

1099.647: [GC [YG occupancy: 3308479 K (4960000 K)]
1099.648: [GC 1099.649: [ParNew: 3308479K->42384K(4960000K), 0.1420310 secs]
7421787K->4180693K(10080000K), 0.1447160 secs] [Times: user=2.69 sys=0.03, real=0.15 secs]

1099.793: [Rescan (parallel) , 0.0121000 secs]1099.805: [weak refs processing, 0.0664790 secs] 
[1 CMS-remark: 4138308K(5120000K)] 4180693K(10080000K), 0.2254870 secs] 
[Times: user=3.00 sys=0.05, real=0.23 secs]

运行时清理(并发)

1104.895: [CMS-concurrent-sweep: 4.970/5.020 secs] 
[Times: user=12.43 sys=1.05, real=5.02 secs]

复原(并发)

1104.908: [CMS-concurrent-reset: 0.012/0.012 secs]
[Times: user=0.03 sys=0.01, real=0.01 secs]

要想知道应用真正的停顿时间,可以使用PrintGCApplicationStoppedTime 参数:

63043.344: [GC [PSYoungGen: 5009217K->34119K(5049600K)] 
5985479K->1034614K(8121600K), 0.1721890 secs] [Times: user=2.62 sys=0.01, real=0.18 secs]

这样看来,真正应用暂停的时间要比stop the world时间还要稍长一点点。


年轻代(eden和Survivor)、年老代的设置选择了GC策略之后,年轻代和年老代的设置就很重要了,如果一味的追求响应时间,可以尽量把年轻代调大一点,youngGC的回收频率减小了,但回收时间也增大了,5000M的年轻代,平均回收时间在150+ms,3000M的年轻代平均回收时间在90+ms

如果一味的增大年轻代,CMS前提下的年老代的威力也发挥不出来,更容易出现promotion failed导致一次FullGC

但如果一味的调小年轻代,虽然单次回收时间减小,但回收频率会陡增,应用STW时间也会增加,总体年轻代回收的时间也可能会增大,所以调整年轻代和年老代的比例就是一个找平衡的过程

我的经验是年轻代的比例在2/8到4/8之间,具体情况要看实际应用情况而定。

我们都知道年轻代采用的是“copy”算法,有两个survivor空间,每次回收总有一个是空的,另一个存放的是前几次youngGC存留下来而且还不够提升到old资格的对象,所以有三个参数很重要:

如果设置SurvivorRatio为65536,MaxTenuringThreshold为0就表示禁止使用survivor空间,在这种模式下,对象直接进入old区,而且我发现在这种模式下,photo的resin启动时间大大减少,以前170s在这种模式下只需要90+s,足足降低了一半,因为这个,我顿时对这种模式产生的兴趣,但CMS的压力就增大了,威力根本发挥不出来了,GC的时间没有减少反而增加,remark的时间也增大到3s,最后不得不忍痛割爱放弃了这种模式

-XX:+CMSScavengeBeforeRemark:这个参数还蛮重要的,它的意思是在执行CMS remark之前进行一次youngGC这样能有效降低remark的时间,之前我没有加这个参数,remark时间最大能达到3s,加上这个参数之后remark时间减少到1s之内

-XX:+UseCMSCompactAtFullCollection,用于指定在Full GC之后进行内存整理,内存整理会使得垃圾收集停顿时间变长,CMS提供了另外一个参数。

-XX:CMSFullGCsBeforeCompaction,用于设置在执行多少次不压缩的Full GC之后,跟着再来一次内存整理。

另外,我发现survivor空间并没有像预期的那样大(eden的1/8),通过跟踪JVM的启动过程中发现,JVM在一定的条件下(可能跟parallelGC和默认SurvivorRatio有关会动态调整survivor的大小,避免内存浪费。

感谢各位的阅读,以上就是“虚拟机内存问题和Java虚拟机优化案例分析”的内容了,经过本文的学习后,相信大家对虚拟机内存问题和Java虚拟机优化案例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. tomcat和java虚拟机是什么
  2. Java虚拟机

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jdk java mark

上一篇:CSS3如何模拟动画下拉菜单效果

下一篇:Angular.js如何通过自定义指令directive实现滑块滑动效果

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》