版权声明:本文为横云断岭原创文章,未经博主同意不得转载。微信公众号:横云断岭的专栏 https://blog.csdn.net/hengyunabc/article/details/24924843

缘起

线上有Tomcat升级到7.0.52版,然后有应用的JVM FullGC变频繁。在高峰期socket连接数,Cpu使用率都暴增。

思路

思路是Tomcat本身的代码应该是没有问题的。有问题的可能是应用代码升级,或者环境改变了。总之Tomcat的优先级排在最后。

先把应用的heap dump下来分析下:

jmap -dump:format=b,file=path pid

用IBM的Heap Analyser分析,发现dubbo rpc调用的RpcInvocation对象和taglibs的SimpleForEachIterator对象占用了非常大部分内存。

正常来说。这两种类型的对象都应该能够非常快被回收掉,怎么会占用了那么大的内存空间?是不是有别的对象引用了它们。导致不能释放?

再细致分析。发现RpcInvocation对象都是root refer的,也就是根对象。正常来说根对象应该能够非常快就被回收掉的,为什么在内存中会有那么多对象?

再查看应用的JVM參数:

 

-Xms2g -Xmx2g -Xmn256m -XX:SurvivorRatio=8 -XX:ParallelGCThreads=8 -XX:PermSize=512m -XX:MaxPermSize=512m -Xss256k -XX:-DisableExplicitGC -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled

首先发现应用的新生代,即-Xmn256m 设置得太小了。

对比上面RpcInvocation对象占用了226M。SimpleForEachIterator占用了267M内存。

 

 

 

显然在新生代里,没办法放下那么多的对象,这些对象必定是被放到老生代(old space)里去了。

既然RpcInvocation对象和SimpleForEachIterator对象应该都是能够非常快被回收了,那么思路变成,触发一下线上的FullGC,看下对象有没有被回收。

在触发之前,先用jmap -histo pid统计下对象的数量:
  34:        136762        4376384  com.alibaba.dubbo.rpc.RpcInvocation
 129:         16345         392280  org.apache.taglibs.standard.tag.common.core.ForEachSupport$SimpleForEachIterator
用 jmap -histo:live <pid> 触发Full GC之后:
 294:           625          20000  com.alibaba.dubbo.rpc.RpcInvocation
 495:           292           7008  org.apache.taglibs.standard.tag.common.core.ForEachSupport$SimpleForEachIterator
果然数量大大的降低了。

所以结论比較明显了,新生代(Young generation)的空间太小,导致有一些本应该能够非常快就被回收的对象被放到了老生代(Old generation)里,导致老生代上涨非常快。频繁Full GC。

于是想办法添加新生代的大小,把JVM參数改为:

 

 -Xms2g -Xmx2g -XX:ParallelGCThreads=8 -XX:PermSize=256m -XX:MaxPermSize=512m -Xss256k -XX:-DisableExplicitGC -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled 

由于观察到PermSize实际上仅仅用了不到200M。没有必要设置为512M,浪费内存,所以改为 -XX:PermSize=256m -XX:MaxPermSize=512m 。

 

另外。把新生代最大限制-Xmn256m 去掉。

由于默认的NewRatio = 2。即除了PermSize,新生代大约占内存的1/3,即约(2048 - 256) /3 = 597M。

和原来相比增大了一倍不止。

改动上线之后。观察发现Old Space增长缓慢。FullGC次数大大降低,时间在50ms下,Yong GC都在10ms下。达到了想要的效果。

 

简单的GC过程分析

首先来看一张GC的模型图,非常形象:

简单来说。对于GC,我们了解到这些信息就足够了。

大部分新对象在Eden Space上分配,当Eden Space满了,则要用到Survivor Space来回收。YGC的算法是非常快的。

多次YGC之后,还存活的对象就会被移到Old Generation(old space)上。当Old Generation满了的时候,就会FGC,FGC有通常比較慢。

Permanent Space仅仅要你在開始时分配了足够大的空间。那它能够不用管。

我们能够得出一些结论:

 

  • 合理降低对象进入老生代;
  • Old Space可能会一直增长。有时没有办法避免不让对象进入Old Space,当然也有一些程序是从来都不运行FGC的;
  • 是不是尽全力防止对象进入老生代?显然不是,有些对象假设长久存在在新生代里,显然加重了YGC的负担,多次YGC之后仍然存活的对象显然应该放到Old Space里。

 

理想的GC/内存使用情况

总结下来。能够发现。理想的GC情况应该是这种:

Old Space增长缓慢,FullGC次数少,FullGC的时间短(大部情况应该要在1秒内)。

总结:

尽量少加上一些默认參数。这点我非常赞同RednaxelaFX的看法,配置了默认參数除了让后面调优的人蛋疼之外,没有太多的帮助。

GC调优就是一个取舍权衡的过程。有得必有失,最好能够在多个不同的实例里,配置不同的參数,然后进行比較。

有非常多命令行工具或者图形工具能够使用。好的工具事半功倍。

參考:

http://www.alphaworks.ibm.com/tech/heapanalyzer‎    IBM Heap Analyser

http://hllvm.group.iteye.com/group/topic/27945    JVM调优的"标准參数"的各种陷阱,RednaxelaFX 出品,强列推荐

http://www.taobaotesting.com/blogs/2392      JAVA性能剖析1——JVM内存管理与垃圾回收

http://www.oschina.net/translate/using-headless-mode-in-java-se      在 Java SE 平台上使用 Headless 模式

 

公众号

欢迎关注公众号:横云断岭的专栏,专注分享Java,Spring Boot。Arthas,Dubbo。

JVM GC调优一则--增大Eden Space提高性能的更多相关文章

  1. JVM GC调优一则–增大Eden Space提高性能

    缘起 线上有Tomcat升级到7.0.52版,然后有应用的JVM FullGC变频繁,在高峰期socket连接数,Cpu使用率都暴增. 思路 思路是Tomcat本身的代码应该是没有问题的,有问题的可能 ...

  2. jvm gc 调优 实战

    非常不错的文章们 转自: 中文:http://blog.csdn.net/dragonassassin/article/details/51010947 http://josh-persistence ...

  3. JVM 自带性能监测调优工具 (jstack、jstat)及 JVM GC 调优

    1. jstack:占用最多资源(CPU 内存)的Java代码 https://www.cnblogs.com/chengJAVA/p/5821218.html https://blog.csdn.n ...

  4. 一张PDF了解JDK10 GC调优秘籍-附PDF下载

    目录 简介 Java参数类型 Large Pages JIT调优 总结 简介 今天我们讲讲JDK10中的JVM GC调优参数,JDK10中JVM的参数总共有1957个,其中正式的参数有658个. 其实 ...

  5. GC参考手册 —— GC 调优(基础篇)

    GC调优(Tuning Garbage Collection)和其他性能调优是同样的原理.初学者可能会被 200 多个 GC参数弄得一头雾水, 然后随便调整几个来试试结果,又或者修改几行代码来测试.其 ...

  6. 一张PDF了解JDK9 GC调优秘籍-附PDF下载

    目录 简介 Oracle中的文档 JDK9中JVM参数的变化 废弃的JVM选项 不推荐(Deprecated)的JVM选项 被删除的JVM参数 JDK9的新特性Application Class Da ...

  7. 深入JVM系列(二)之GC机制、收集器与GC调优

    一.回想JVM内存分配 须要了解很多其它内存模式与内存分配的,请看 深入JVM系列(一)之内存模型与内存分配 1.1.内存分配: 1.对象优先在EDEN分配 2.大对象直接进入老年代  3.长期存活的 ...

  8. 深入JVM系列(二)之GC机制、收集器与GC调优(转)

    一.回顾JVM内存分配   需要了解更多内存模式与内存分配的,请看 深入JVM系列(一)之内存模型与内存分配 1.1.内存分配: 1.对象优先在EDEN分配2.大对象直接进入老年代 3.长期存活的对象 ...

  9. JVM的GC机制及JVM的调优方法

    内存管理和垃圾回收是JVM非常关键的点,对Java性能的剖析而言,了解内存管理和垃圾回收的基本策略非常重要. 1.在程序运行过程当中,会创建大量的对象,这些对象,大部分是短周期的对象,小部分是长周期的 ...

随机推荐

  1. IIS配置支持apk文件下载

    写在前面 最近项目中涉及到移动端的东西,有一个功能是要下载apk文件,apk为安卓安装程序,但是iis默认是不支持该类型的文件下载的. 解决方案 找到该站点,并切换到功能视图 找到MIME类型,双击进 ...

  2. Android性能优化第(一)篇---基本概念

    最近打算总结几篇app性能优化方面的东西,毕竟android弄了这么久,万一到哪些转了行,岁月久了就忘记了,纯粹当个人笔记.今个是第一篇---性能优化的基本概念,毛主席说了,让理论先行,理论指导实践. ...

  3. iis无法启动的解决办法-卸掉KB939373补丁

    在本地计算机无法启动 world wide web Publishing 服务错误127:找不到指定的程序 在网上搜索了一下,发现,回答的五花八门, 1.有的说重新安装IIS的,(我重新安装了,还是不 ...

  4. 查找python项目依赖并生成requirements.txt

    1.如果使用virtualenv环境,直接使用 pip freeze > requirements.txt ➜  ~ .virtualenvs/xxx/bin/pip freeze > r ...

  5. SQLite创建表并加入数据

    - (void)viewDidLoad { [super viewDidLoad]; //创建表 [self creatTable]; //插入数据 [self insertTable]; } // ...

  6. Linux内核的引导

    1,当系统上电或复位时,CPU会将PC指针赋值为一个特定的地址0xFFFF0并执行该地址处的指令.在PC机中,该地址位于BIOS中,它保存在主板上的ROM或Flash中 2,BIOS运行时按照CMOS ...

  7. 计算机网络自顶向下第三章传输层二TCP

    TCP 全双工 A-B,B-A 点对点 一对一的 TCP连接建立过程 客户首先发送一个特殊的TCP报文段,服务器用另一个特殊的TCP报文段来相应,最后,客户再用第三个特殊的报文段作为相应,前两个报文段 ...

  8. openLayers加载高德地图

    之前用openlayers对高德,百度,腾讯,bing,supermap,天地图,arcgis,google等地图进行了对接,今天简单介绍一下openlayers+高德: 在Openlayers.La ...

  9. 浅谈PHP与手机APP开发即API接口开发

    API(Application Programming Interface,应用程序接口)架构,已经成为目前互联网产品开发中常见的软件架构模式,并且诞生很多专门API服务的公司,如:聚合数据(http ...

  10. UNP学习笔记(第二章:传输层)

    本章的焦点是传输层,包括TCP.UDP和SCTP. 绝大多数客户/服务器网络应用使用TCP或UDP.SCTP是一个较新的协议. UDP是一个简单的.不可靠的数据报协议.而TCP是一个复杂.可靠的字节流 ...