文档章节

jvm调优尝试

起色
 起色
发布于 2014/04/10 20:17
字数 1868
阅读 277
收藏 14
点赞 2
评论 4

本次调优主要是基于周志明的《深入理解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其实是有的)比较适用于目前情况


© 著作权归作者所有

共有 人打赏支持
起色
粉丝 5
博文 2
码字总数 1868
作品 0
深圳
加载中

评论(4)

jdk2010
jdk2010
顶一下
时间在追我
时间在追我
79赞一个
石头哥哥
石头哥哥
总结的很不错 79
sundy-li
sundy-li
怒赞一记,起色处女作,火前留名
成为Java GC专家(5)—Java性能调优原则

这是“成为Java GC专家”系列的第五篇文章。在第一篇深入浅出Java垃圾回收机制中,我们已经学习了不同的GC算法流程、GC的工作原理、新生代(Young Generation)和老年代(Old Generation)的...

stefanzhlg
2014/12/05
0
1
《成神之路-基础篇》JVM——JVM参数及调优(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 JVM参数及调优 JVM实用参数系列 成为Java GC专家(5)...

05/05
0
0
JVM参数调优:Eclipse启动实践

JVM参数调优:Eclipse启动实践 本文主要参考自《深入理解 Java 虚拟机》。 这本书是国人写的难得的不是照搬代码注释的且不是废话连篇的技术书,内容涵盖了 Java 从源码到字节码到执行的整个过...

天天顺利
2015/01/13
0
0
JVM性能优化, Part 5:Java的伸缩性

ImportNew注: JVM性能优化系列文章前4篇由ImportNew翻译(第一篇,第二篇,第三篇, 第四篇)。本文由新浪微博:吴杰 (@WildJay) 投稿至ImportNew。感谢吴杰! 如果你希望分享好的原创文章或...

梁杰_Jack
2014/10/30
0
0
如何合理的规划一次jvm性能调优

这是jvm优化系列第三篇: jvm优化——垃圾回收 jvm优化——监控工具 JVM性能调优涉及到方方面面的取舍,往往是牵一发而动全身,需要全盘考虑各方面的影响。但也有一些基础的理论和原则,理解...

wier
2017/10/25
0
9
大型互联网架构必备技术——性能调优专题

性能调优 深入内核,直击故障 ,拒绝蒙圈 性能优化如何理解 1、性能基准 2、什么是性能优化 3、衡量标准 JVM调优 1、Jvm虚拟机内存剖析 2、垃圾收集器 3、实战调优案例与解决方案 4、Jvm运行...

Java高级架构
04/15
0
0
深入理解JVM学习笔记(一、总览)

1、JVM历史 2、JVM内存结构 3、JVM垃圾回收机制 4、JVM性能监控工具 5、JVM性能调优案例时间 6、JVM类文件结构 7、JVM类加载机制 8、JVM字节码执行引擎 9、JVM虚拟机编译及其运行时优化 10、...

jintaohahahaha
05/28
0
0
Java中for(;;)和while(true)有啥区别?

群里面有小伙伴提了个问题,说在看并发源码的时候,很多时候源码中都使用for(;;)而不是使用while(true),这两个有什么区别吗? 这种问题,在java里面,最简单有效的办法就是打印字节码看一下,...

若鱼1919
07/11
0
0
java远程调试与JVM调优工具

Java远程调试方法: 1、被调试程序当作调试服务器(本地主动连接远程服务器,需要用如下命令让远程服务器jvm开启调试模式)。 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8765 ...

chape
2013/12/24
0
0
JVM性能调优监控工具jps、jstack、jmap、jhat、jstat、hprof使用详解

现实企业级Java开发中,有时候我们会碰到下面这些问题: OutOfMemoryError,内存不足 内存泄露 线程死锁 锁争用(Lock Contention) Java进程消耗CPU过高 ...... 这些问题在日常开发中可能被...

优雅先生
2014/01/28
0
25

没有更多内容

加载失败,请刷新页面

加载更多

下一页

工作笔记

在list的for-each循环中,直接remove会报java.util.ConcurrentModificationException,但是在remove后面加上break就不会报错了 如果不是每次重新组装,提供出去的配置信息必须以深度克隆的方...

lost_keke
9分钟前
0
0
TensorFlow 退化学习率

随着训练次数的增多,开始时学习率较大,可以较快的收敛到最优解附近,之后学习率应该比较小 exponential_decay 设置每隔一定的学习步数就将学习率下降到指定标准 下面是每隔10步,学习率会下...

阿豪boy
10分钟前
0
0
01、centos7安装docker

1、首先在安装之前检查系统内核版本 [root@docker01 ~]# uname -r3.10.0-327.el7.x86_64[root@docker01 ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) [root@......

北岩
14分钟前
0
0
iptables filter表 nat表 应用实例

iptables基础实例 iptables -nvL 查看规则 [root@localhost ~]# iptables -nvLChain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source ......

李超小牛子
16分钟前
0
0
什么?你的私钥泄漏了?

代码签名是一种当代标准做法,其中软件开发人员通过可信证书颁发机构的验证,并接收可用于签署脚本和可执行文件的证书和私钥。 几乎每个设备,操作系统和网络浏览器都经过硬编码,以尽可能少...

亚洲诚信
20分钟前
1
0
Iterm2安装Zsh + Oh My Zsh+Solarized

安装Oh My Zsh curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh 安装Zsh: 1.安装zsh brew install zsh 2.配置iterm2 sudo vim /etc/shells输入:......

孟飞阳
28分钟前
0
0
缓解ddos攻击的有效解决办法

因为防火墙无法处理所有类型的ddos攻击,下一代防火墙生成内置的DDoS防御,但是无法处理所有类型的攻击。对抗DDoS攻击的最佳做法是有专属的设备或者服务在攻击透过防火墙或者其他的IT基础设施...

上树的熊
28分钟前
0
0
Spark Streaming如何使用checkpoint容错

在互联网场景下,经常会有各种实时的数据处理,这种处理方式也就是流式计算,延迟通常也在毫秒级或者秒级,比较有代表性的几个开源框架,分别是Storm,Spark Streaming和Filnk。 伦理片 http...

刺猬一号
30分钟前
1
0
Xamarin Essentials教程地理定位Geolocation

Xamarin Essentials教程地理定位Geolocation 通过地理定位功能,应用程序可以获取用户的当前地理位置,如经纬度值。利用地理位置,可以在地图上定位,也可以转化物理位置,划分用户的归属地。...

大学霸
43分钟前
0
0
vue 编译警告 Compiled with 4 warnings

There are multiple modules with names that only differ in casing. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic. Use equal casing.......

落雪飞声
47分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部