文档章节

cms优化之晋升失败

Mr_Qi
 Mr_Qi
发布于 2017/07/25 16:30
字数 882
阅读 188
收藏 3

背景

最近系统的用户使用越来越多,随之而来的情况导致系统在运行一段时间后开始出现fgc(频次大约1天2次),cms作为高响应速度的collector,一般我们会尽量避免出现remark或者尽量减低remark的时间(remark阶段会出现stop the world)

我们关注一下zabbix的内存监控图

注:系统为jdk7

如上两张图分别对应堆内存的使用和老年代的使用

从上图可以看出,基本上minor gc比较频繁(第一张的锯齿),并没有出现内存泄露(第一张图在fgc的回收下内存占用几乎不变)

那么出现一次较大的fgc的原因是什么呢?

我们参看一下当前系统的情况

小知识,cms在一次remark前后各算一次fgc

基本看出老年代使用并不高,而年轻代比较小,伊甸园去仅为209m ,幸存者区域约为26m(换句话说,一次晋升最多可能晋升26+209M)

我们看到此次晋升失败,而老年代从2.3g直接fullgc到了500m,存在1.8g的内存回收。中断时间约为2.69s

初步考虑内存分配不合理导致年轻代过小,出现多次的minor gc(minor gc的频率直接决定了对象的年龄,而年龄又决定了晋升到老年代的时机)-XX:MaxTenuringThreshold 最大为15

查看一下我们的jvm参数

 /usr/java/jdk1.7.0_80/bin/java -Djava.util.logging.config.file=/mnt/apache-tomcat-7.0.70-erp/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Xms2048m -Xmx3072m -XX:PermSize=128m -XX:MaxNewSize=256m -XX:MaxPermSize=256m -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -Xloggc:/mnt/apache-tomcat-7.0.70-erp/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/mnt/apache-tomcat-7.0.70-erp -Djava.endorsed.dirs=/mnt/apache-tomcat-7.0.70-erp/endorsed -classpath /mnt/apache-tomcat-7.0.70-erp/bin/bootstrap.jar:/mnt/apache-tomcat-7.0.70-erp/bin/tomcat-juli.jar -Dcatalina.base=/mnt/apache-tomcat-7.0.70-erp -Dcatalina.home=/mnt/apache-tomcat-7.0.70-erp -Djava.io.tmpdir=/mnt/apache-tomcat-7.0.70-erp/temp org.apache.catalina.startup.Bootstrap start

WTF 居然设置了-XX:MaxNewSize为256m,那么默认的surviorRatio为8 也就是 s0=25.6m s1=25.6m eden=204.8m 

为了减低cms在gc时remark时间 考虑调大年轻代,这样对象分配时在年轻代,由于年轻代足够大,不会频繁发生minor gc,这样对象的年龄不会变大的太快。所以需要设置合理的newRatio。

export CATALINA_OPTS="$CATALINA_OPTS -Xms2048m -Xmx3072m -XX:PermSize=128m -XX:NewRatio=3 -XX:MaxPermSize=256m -XX:CMSInitiatingOccupancyFraction=72 -XX:ParallelGCThreads=4 -XX:+UseConcMarkSweepGC -Xloggc:/mnt/apache-tomcat-7.0.70-erp/logs/gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+DisableExplicitGC  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/mnt/apache-tomcat-7.0.70-erp"

将年轻代设置为512m~768m

同时加上-XX:CMSInitiatingOccupancyFraction

该参数表示在老年代达到72%时将强行发生fgc,优先回收内存,以防止出现年轻代晋升失败的情况。

年轻代晋升失败条件如下(不考虑内存碎片):

幸存者+伊甸园区<老年代剩余

采用默认比例 surviorRatio 为8 

此处newRatio为3

公式为

(1+surviorRatio)/(2+surviorRatio)*new <=old*(1-CMSInitiatingOccupancyFraction/100)

得出CMSInitiatingOccupancyFraction约为70 此处使用72(经验值)

原先设置年轻代大小应该是老的jvm参数,当修改了xmx之后没有更新该值,导致年轻代过小

因此此处考虑使用ratio

以观后效

经过改造 目前zabbix的内存使用图如下(最后一天)

基本上可以在老年代达到一定容量时就回收掉,同时stw时间明显降低

原来统计从运行3天暂停8s降低 到运行1天 暂停0.082s

younggc的频率也有所下降,时间也缩短。

© 著作权归作者所有

共有 人打赏支持
Mr_Qi

Mr_Qi

粉丝 277
博文 356
码字总数 365332
作品 0
南京
程序员
加载中

评论(2)

Mr_Qi
Mr_Qi

引用来自“huihrt”的评论

大佬,在南京的哪一个公司啊

回复@huihrt : 江苏爱福路
h
huihrt
大佬,在南京的哪一个公司啊
cms优化之晋升失败

背景 最近系统的用户使用越来越多,随之而来的情况导致系统在运行一段时间后开始出现fgc(频次大约1天2次),cms作为高响应速度的collector,一般我们会尽量避免出现remark或者尽量减低remar...

波波维奇
2017/11/30
0
0
《深入理解Java虚拟机》——垃圾收集器参数总结

JDK1.6垃圾收集相关参数 参数 描述 UseSerialGC 虚拟机运行在Client模式下的默认值,打开此开关后,使用Serial+Serial Old的收集器组合进行内存回收 UseParNewGC 打开此开关后,使用ParNew+...

戴的天
2014/08/18
0
0
GC日志分析 & GC常用参数

1:GC日志分析 最前面的数字 33.125 和 100.667 代表了GC的执行时间,是从Java虚拟机启动以来经过的秒数。 “GC”和“Full GC”说明了这次垃圾收集的停顿类型。如果有“Full”则说明 GC 发生...

ZHAOBEN
2016/04/26
64
0
《Java性能优化权威指南》读书笔记(二)

JVM性能调优入门 ----- 基本原则 Minor GC回收原则,尽可能多的收集垃圾 GC内存最大化原则,堆越大越好 GC调优3选2原则,吞吐量、延迟、内存占用 关注吞吐量和延迟的Java应用程序,都应该将-...

selfless
2016/07/03
101
3
Java虚拟机学习 - 垃圾收集器

HotSpot JVM收集器 上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器。如果两个收集器之间存在连线,就说明它们可以搭配使用。 Serial(串行GC)收集器 Serial收集器是一个...

星逝流
2016/02/17
13
0

没有更多内容

加载失败,请刷新页面

加载更多

java JDK动态代理

本篇随笔是对java动态代理中的JDK代理方式的具体实现。 首先需要定义一个接口,为其定义了两个方法:   public interface UserService { public void add(); public void delete(); } 然后需...

编程SHA
25分钟前
2
0
轻松理解Dubbo分布式服务框架

Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的...

别打我会飞
33分钟前
2
0
TypeScript基础入门之JSX(一)

转发 TypeScript基础入门之JSX(一) 介绍 JSX是一种可嵌入的类似XML的语法。 它旨在转换为有效的JavaScript,尽管该转换的语义是特定于实现的。 JSX在React框架中越来越受欢迎,但此后也看到了...

durban
57分钟前
1
0
JavaScript使用原型判断对象类型

1. constructor属性 在JavaScript创建对象(二)——构造函数模式中,我们说过可以使用对象的constructor属性判断对象的类型:p1.constructor === Person,可能当时就有细心的读者会想,我们...

Bob2100
59分钟前
1
0
10-《深度拆解JVM》JVM是怎么实现invokedynamic的?(下)

一、问题引入 上回讲到,为了让所有的动物都能参加赛马,Java 7 引入了 invokedynamic 机制,允许调用任意类的“赛跑”方法。不过,我们并没有讲解 invokedynamic,而是深入地探讨了它所依赖...

飞鱼说编程
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部