jvm调优尝试
博客专区 > 起色 的博客 > 博客详情
jvm调优尝试
起色 发表于4年前
jvm调优尝试
  • 发表于 4年前
  • 阅读 262
  • 收藏 14
  • 点赞 2
  • 评论 4

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 对JAVA虚拟机的内存环节有了初步的认识,可以看懂大部分参数,正在尝试去调优

本次调优主要是基于周志明的《深入理解java虚拟机》里的知识,结合自己百度google以及一些参考资料和现有前端机的运行情况进行的。


内存介绍

在进入主题之前,先说一下JVM的内存分配,主要分为栈,本地方法栈,方法区,常量池,程序计数器和直接内存,一般我们很少会用到直接内存,nio里的一些方法会用到,而且直接内存的是不会显示到jvm里的,详情看下图


这些内存分别对应于jvm参数的哪些东西呢,我举一些常用的

-Xmn 年轻代,包括eden+from+to 

-Xms 初始化堆大小   包括 年轻代,年老代,持久代,包括方法区(说包括是因为在JAVA虚拟机的定义里是包括,GC时我看成不包括,我把它看成Perm),

-Xmx 最大的堆大小  同上,一般正式环境都会把Xms和Xmx设置为一样的,防止内存重新分配

-XX:MaxNewSize  最大年轻代大小

-XX:PermSize  初始技久代大小

-XX:MaxPermSize 最大持久代大小

-XX:SurvivorRatio    eden/from(to)  就是 eden和from 的比值,这里是因为新生代基本上都是采用coping算法,所以会有一个from和to,关于这个算法,后面简单介绍一下

-XX:NewRatio 就是年老代和年轻代的比值,一般设置了Xmn及(Xms和Xmx值是一样的)这个就没有必须了,因为年老代就是  Xmx-Xmn 了

基本常用的就这些了,当然明细后面也有参考资料


常用算法

标记清除mark-sweep

最基本的算法,就是把内存标识之后再清除,优点简单(对于JVM来说),缺点效率较低,碎片比较多

jvm_mark-sweep

复制算法(coping)

使用两块内存,留一块先不用,一边用的满了之后,把还留下的全部复制到另一块,清除原有快,优点,简单高效,缺点,得留一块内存

jvm_copying


标记-整理,mark-compact

基本上就是用一块内存实现了上面的方法,(优缺点书上也不说。。。),个人感觉,比上面效率肯定要低点

jvm_mark-compact

分代收集

不同代用不同的算法,就是上面三种的组合,有一些是指定了两种组合


回收收集器

Serial收集器

年轻代的单线程收集,采用的是coping算法,优点,简单高效(与其他单线程相比),缺点,停顿时间长

ParNew收集器

多线程版本的Serial,只是有一些参数来控制线程等


Parallel Scavenge收集器

和ParNew是一样的(所谓一样是因为年轻代和年老代的算法就这几种),但是这个可以用参数控制吞吐量,也是-server模式的默认收集器,公司之前的版本用的是这个,对于年老代比较大的回收暂停时间有点长


SerialOld 和 ParOld 收集器

老年代的对应版本


CMS收集器

concurrent mark sweep ,是一种以获取最短的停顿时间为目标的收集器,重视响应速度,(参数得当,对full gc有很大的提升,young gc时间和次数也没有比Parallel Scavenge提高多少)


实战

终于到了这篇文章的核心环节了

公司内部系统,约900W PV,6台前端机器 8G 4核

公司架构是 struts2 + spring + springjdbc ,然后memcached也有,redis也有,本地缓存也有,显示直接用jsp

之前的JVM参数

-Xms1536m -Xmx3000m -XX:MaxGCPauseMillis=850 -Xss1000k -XX:NewRatio=2 -XX:PermSize=128M -XX:MaxNewSize=512M -XX:MaxPermSize=512M -Dresin.home=/usr/local/resin -Dserver.root=/usr/local/resin -Djava.util.logging.manager=com.caucho.log.LogManagerImpl -XX:+UseParallelGC -XX:+UseNUMA -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -verbosegc -XX:+PrintGCDetails

当然这套JVM参数里有很多硬伤,首先,Xms和Xmx不一样,这个影响确实有点大,会对old区的最大内存一直在变动,还有就是Xss1000k,改为了1m。full gc平均3S,young gc平均80ms,吞吐量98%左右,jstat情况如下

就不贴gcview查看的图了,而且也很难看,因为old的变动

学习了这些知识之后,稍微进行了一点修改,因为看到Old比较大,都达到了1G,所以考虑用ParallelOldGC,把old区改为多线程,但是效果不是很好,和这个差不多,原因未知,若有人知可留言,谢谢

于是尝试先改硬伤,把内存改小了一点,因为old区太大了怕回收更耗时

-Xms2560m -Xmx2560m -Xss1m -XX:SurvivorRatio=8(因为看到from或to的总容量一直在变化,所以指定死,8也是默认的值) -XX:+UseParallelGC

还是用的ParallelGC,先不敢改动太大

改动后确实有点效果,因为old 2G了,所以old区一开始的增速较慢,但是执行几次full gc后,gc后基本上在1.2G,而且full gc时间也没有多大变化,还是平均3S,但是full gc的次数明显下来了

但是这次的改动还是不够明显,因为bs架构的full gc时间太长,肯定有一部分人在暂停时访问等待时间过长,于是,开始考虑用cms收集,因为给力也是给力在old区嘛,最后找了一系列实战资料,最终确定为

/usr/java/jdk64bit/bin/java -Xms2560m -Xmx2560m -Xmn512m -Xss1m -XX:SurvivorRatio=8 -XX:MaxNewSize=512m -XX:MaxPermSize=256M -XX:PermSize=128M -Djava.util.logging.manager=com.caucho.log.LogManagerImpl -XX:+DisableExplicitGC -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=75 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -verbosegc -XX:+PrintGCDetails

以下这个图,full gc次数和每次的时间明显减少,虽然young gc多了一点点,但是总的时间也降下来了,吞吐量也提高了,略有成就感


总结

以上3个图都是同一时刻起(并且跑了3个钟头)的不同机器gc情况,我们发布的时候有一定的时间差,也就一两分钟吧,忽略不记了

另外,这次改动主要是硬伤的改动,CMS的改动总GC时间这块比之前的少的不算多,但是full gc(3S到200ms)比较给力,另外,就是整个项目的young gc比较慢,平均90ms的,full gc 次数也比较多,3个小时14次,担保内存也是满足的,这个希望有牛人能够指导一下


参考资料:

内存介绍:http://www.blogjava.net/nkjava/archive/2012/03/14/371831.html

JVM算法:http://hi.baidu.com/michaleyz/item/60d847da7e69e51920e2507c

CMS详细:http://www.cnblogs.com/redcreen/archive/2011/05/05/2038331.html

(xmemcache作者 丹哥)http://www.blogjava.net/killme2008/archive/2009/09/22/295931.html


-----------------------------------------------------------------------------------

补充一张GCView 对比图

最上面那个是 -Xms1536m -Xmx3000m的那个,因为old区不稳定,所以full gc次数最多,总gc时间也最长

第二个只改动了Xms和Xmx保持一致,old区稳定,因为是ParNew + SerialOld 算法,以吞吐量优先,但是full gc时间还是很长

最后这个,是用CMS搜集,最大的缺点就是old只用了75%,因为要防止promotion fail,但是每次回收都很干净,回收幅度大,另一个缺点就是吞吐量随着时间增长,可能不如第二种,但是full gc次数和时间都大幅度降低(这里显示为0其实是有的)比较适用于目前情况


标签: jvm 内存 调优
共有 人打赏支持
粉丝 6
博文 2
码字总数 1868
评论 (4)
sundy-li
怒赞一记,起色处女作,火前留名
石头哥哥
总结的很不错 79
时间在追我
79赞一个
jdk2010
顶一下
×
起色
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: