JVM调优的几种策略

开发 后端
你对JVM调优的概念是否熟悉 ,这里和大家分享一下,主要包括串行垃圾回收,并行回收,并发回收和增量回收等内容,相信本文介绍一定会让你有所收获。

JVM参数调优是一个很头痛的问题,可能和应用有关系,别人说可以的对自己不一定管用。下面是本人一些JVM调优的实践经验,希望对读者能有帮助,环境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G内存,dell2950服务器。

JVM调优

一:JVM调优之串行垃圾回收

也就是默认配置,完成10万request用时153秒。JVM参数配置如下: 

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server  
  2.  
  3. -Xms2048M-Xmx2048M-Xmn512M
  4. -XX:PermSize=256M-XX:MaxPermSize=256M 
  5.  
  6. -XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19 
  7.  
  8. -Xnoclassgc-Xloggc:log/gc.log
  9. -XX:+PrintGCDetails-XX:+PrintGCTimeStamps";  

这种配置一般在resin启动24小时内似乎没有大问题,网站可以正常访问,但查看日志发现,在接近24小时时,FullGC执行越来越频繁,大约每隔3分钟就有一次FullGC,每次FullGC系统会停顿6秒左右,作为一个网站来说,用户等待6秒恐怕太长了,所以这种方式有待改善。MaxTenuringThreshold=7表示一个对象如果在救助空间移动7次还没有被回收就放入年老代,GCTimeRatio=19表示java可以用5%的时间来做垃圾回收,1/(1+19)=1/20=5%。

二:JVM调优之并行回收

完成10万request用时117秒,配置如下: 

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server-Xmx2048M  
  2. -Xms2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M 
  3. -Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails  
  4. -XX:+PrintGCTimeStamps-XX:+UseParallelGC-XX:ParallelGCThreads=20 
  5. -XX:+UseParallelOldGC-XX:MaxGCPauseMillis=500 
  6. -XX:+UseAdaptiveSizePolicy-XX:MaxTenuringThreshold=7 
  7. -XX:GCTimeRatio=19";  

并行回收我尝试过多种组合配置,似乎都没什么用,resin启动3小时左右就会停顿,时间超过10秒。也有可能是参数设置不够好的原因,MaxGCPauseMillis表示GC***停顿时间,在resin刚启动还没有执行FullGC时系统是正常的,但一旦执行FullGC,MaxGCPauseMillis根本没有用,停顿时间可能超过20秒,之后会发生什么我也不再关心了,赶紧重启resin,尝试其他回收策略。

三:JVM调优之并发回收

完成10万request用时60秒,比并行回收差不多快一倍,是默认回收策略性能的2.5倍,配置如下: 

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server  
  2. -Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M 
  3. -XX:MaxPermSize=256M-XX:+UseConcMarkSweepGC  
  4. -XX:MaxTenuringThreshold=7-XX:GCTimeRatio=19 
  5. -Xnoclassgc-Xloggc:log/gc.log-XX:+PrintGCDetails  
  6. -XX:+PrintGCTimeStamps-XX:+UseCMSCompactAtFullCollection  
  7. -XX:CMSFullGCsBeforeCompaction=0"; 

这个配置虽然不会出现10秒连不上的情况,但系统重启3个小时左右,每隔几分钟就会有5秒连不上的情况,查看gc.log,发现在执行ParNewGC时有个promotionfailed错误,从而转向执行FullGC,造成系统停顿,而且会很频繁,每隔几分钟就有一次,所以还得改善。UseCMSCompactAtFullCollection是表是执行FullGC后对内存进行整理压缩,免得产生内存碎片,CMSFullGCsBeforeCompaction=N表示执行N次FullGC后执行内存压缩。#p#

四:JVM调优之增量回收

完成10万request用时171秒,太慢了,配置如下: 

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server  
  2. -Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M 
  3. -XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7 
  4. -XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log  
  5. -XX:+PrintGCDetails-XX:+PrintGCTimeStamps-Xincgc"; 

似乎回收得也不太干净,而且也对性能有较大影响,不值得试。

五:JVM调优之并发回收的I-CMS模式

和增量回收差不多,完成10万request用时170秒。配置如下: 

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server  
  2. -Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M 
  3. -XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7 
  4. -XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log  
  5. -XX:+PrintGCDetails-XX:+PrintGCTimeStamps  
  6. -XX:+UseConcMarkSweepGC-XX:+CMSIncrementalMode  
  7. -XX:+CMSIncrementalPacing  
  8. -XX:CMSIncrementalDutyCycleMin=0 
  9. -XX:CMSIncrementalDutyCycle=10-XX:-TraceClassUnloading"; 

采用了sun推荐的参数,回收效果不好,照样有停顿,数小时之内就会频繁出现停顿,什么sun推荐的参数,照样不好使。

六:JVM调优之递增式低暂停收集器

又叫什么火车式回收,完成10万request用时153秒,配置如下: 

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server  
  2. -Xms2048M-Xmx2048M-Xmn512M-XX:PermSize=256M 
  3. -XX:MaxPermSize=256M-XX:MaxTenuringThreshold=7 
  4. -XX:GCTimeRatio=19-Xnoclassgc-Xloggc:log/gc.log  
  5. -XX:+PrintGCDetails-XX:+PrintGCTimeStamps-XX:+UseTrainGC"; 

该配置效果也不好,影响性能,所以没试。

七:相比之下,还是并发回收比较好,性能比较高,只要能解决ParNewGC(并行回收年轻代)时的promotionfailed错误就一切好办了,查了很多文章,发现引起promotionfailed错误的原因是CMS来不及回收(CMS默认在年老代占到90%左右才会执行),年老代又没有足够的空间供GC把一些活的对象从年轻代移到年老代,所以执行FullGC。CMSInitiatingOccupancyFraction=70表示年老代占到约70%时就开始执行CMS,这样就不会出现FullGC了。SoftRefLRUPolicyMSPerMB这个参数也是我认为比较有用的,官方解释是softlyreachableobjectswillremainaliveforsomeamountoftimeafterthelasttime
theywerereferenced.Thedefaultvalueisonesecondo
flifetimeperfreemegabyteintheheap,我觉得没必要等1秒,所以设置成0。配置如下

  1. $JAVA_ARGS.="-Dresin.home=$SERVER_ROOT-server-Xms2048M  
  2. -Xmx2048M-Xmn512M-XX:PermSize=256M-XX:MaxPermSize=256M 
  3. -XX:SurvivorRatio=8-XX:MaxTenuringThreshold=7 
  4. -XX:GCTimeRatio=19-Xnoclassgc-XX:+DisableExplicitGC  
  5. -XX:+UseParNewGC-XX:+UseConcMarkSweepGC  
  6. -XX:+CMSPermGenSweepingEnabled  
  7. -XX:+UseCMSCompactAtFullCollection  
  8. -XX:CMSFullGCsBeforeCompaction=0 
  9. -XX:+CMSClassUnloadingEnabled-XX:-CMSParallelRemarkEnabled  
  10. -XX:CMSInitiatingOccupancyFraction=70 
  11. -XX:SoftRefLRUPolicyMSPerMB=0-XX:+PrintClassHistogram  
  12. -XX:+PrintGCDetails-XX:+PrintGCTimeStamps  
  13. -XX:+PrintGCApplicationConcurrentTime  
  14. -XX:+PrintGCApplicationStoppedTime  
  15. -Xloggc:log/gc.log"; 

上面这个配置内存上升的很慢,24小时之内几乎没有停顿现象,最长的只停滞了0.8s,ParNewGC每30秒左右才执行一次,每次回收约0.2秒,看来问题应该暂时解决了。

参数不明白的可以上网查,本人认为比较重要的几个参数是:

-Xms-Xmx-XmnMaxTenuringThresholdGCTimeRatioUse

ConcMarkSweepGCCMSInitiatingOccupancyFractionSoftRefLRUPolicyMSPerMB

eclipse中配置JVM参数:-Xmx1024M-Xms1000M-server-XX:PermSize=64M-XX:MaxPermSize=128m
 

【编辑推荐】

  1. 经验分享 JVM调优方法总结
  2. JVM调优技巧集锦
  3. 巧解Tomcat中JVM内存溢出问题
  4. 新一代JVM垃圾回收算法出炉
  5. 揭露JDK,JRE,JVM三者不为人知的隐情

 

 

责任编辑:佚名 来源: blog.sina.com.cn
相关推荐

2012-01-10 14:35:08

JavaJVM

2017-07-21 08:55:13

TomcatJVM容器

2023-11-11 19:07:23

JVMJava

2023-11-10 11:23:20

JVM内存

2022-09-20 14:11:37

JVM调优命令

2010-09-26 13:39:46

JVM调优

2012-01-10 15:13:56

JavaJVM

2010-09-26 09:08:17

JVM调优

2019-12-20 14:21:26

JVM调优垃圾回收

2010-09-25 15:52:27

JVM内存JVM

2021-06-03 08:32:18

JVM调优虚拟机

2017-10-17 14:02:30

jvm调优工具

2017-09-22 15:15:23

jvm调优命令

2010-09-25 13:05:07

JVM参数

2010-03-04 10:56:52

JVM参数

2010-09-26 10:53:00

JVM内存调优设置

2021-11-21 23:03:38

jvm调优虚拟机

2023-02-10 09:28:23

优化工具

2019-02-19 10:25:28

JVM性能工具

2020-08-03 07:00:00

Snowflake数据库性能调优
点赞
收藏

51CTO技术栈公众号