目录

  • 一、内存调优的目标
  • 二、估算内存运转模型
  • 三、YoungGC 调优1、合理分配内存降低YoungGC频率2、保证Survivor空间足够3、优化对象年龄阀值4、优化大对象阀值5、选择垃圾回收器6、JVM参数
  • 四、FullGC 调优1、多久触发一次 FullGC2、CMS并发失败3、CMS回收后碎片整理频率4、CMS提升FullGC的性能5、禁用System.gc6、元空间优化7、JVM参数
  • 五、大内存机器GC调优1、使用大内存机器的场景2、大内存机器的问题3、G1回收器调优
  • 六、OOM内存溢出问题1、元空间溢出2、栈溢出3、堆溢出4、堆外内存溢出5、OOM问题如何解决
  • 七、性能调优总结1、调优过程总结2、频繁FullGC的几种表现3、频繁FullGC的几种常见原因4、JVM参数模板
  • 八、JVM参数1、JVM标准参数(-)2、JVM非标准参数(-X)3、JVM非Stable参数(-XX)4、即时编译调优参数
  • 参考

前序文章:

JVM性能调优(1) —— JVM内存模型和类加载运行机制

JVM性能调优(2) —— 垃圾回收器和回收策略

回到顶部

一、内存调优的目标

新生代的垃圾回收是比较简单的,Eden区满了无法分配新对象时就触发 YoungGC。而且新生代采用的复制算法效率极高,加上新生代存活的对象很少,只要迅速标记出这少量存活对象,移动到Survivor区,然后快速回收掉Eden区,速度很快。一般一次YoungGC就耗费几毫秒或几十毫秒,所以新生代GC对系统的影响基本不是很大。

但老年代的GC就不一样了,老年代GC通常都很耗费时间,尤其是频繁触发老年代GC(FullGC/OldGC)。因为无论是CMS垃圾回收器还是G1垃圾回收器,比如说CMS就要经历初始标记、并发标记、重新标记、并发清理、碎片整理几个环节,过程非常的复杂,STW的时间也会更长,G1同样也是如此。通常来说,FullGC至少比YoungGC慢10倍以上。

新生代对象进入老年代有四个时机:对象年龄超过阀值、大对象直接进入老年代,动态年龄判断规则、新生代GC后存活对象太多无法放入Survivor区。对象年龄太大进入老年代无可避免,因为这部分对象一般来说都是长期存活的对象,是需要进入老年代的。而后三个一般都是因为内存分配不合理或一些参数设置不合理导致对象进入老年代,而且基本都是生命周期较短的对象,然后占满老年代,触发老年代GC。

因此,基于JVM运行的系统最大的问题,就是因为内存分配、参数设置不合理,导致对象频繁的进入老年代,然后频繁触发FullGC,导致系统每隔一段时间就卡顿几百毫秒甚至几秒钟,这对用户体验来说将是极差的。

所以,JVM调优的目标,最重要的就是对内存分配调优,然后合理优化新生代、老年代、Eden和Survivor各个区域的内存大小。接着再尽量优化参数避免新生代的对象进入老年代,尽量让对象留在新生代里被回收掉,甚至不会出现 FullGC。

回到顶部

二、估算内存运转模型

在设置JVM内存的时候,是没有一个固定标准、固定参数的,但是有一套比较通用的分析和优化方法,就是根据实际业务预估这个系统未来的业务量、访问量,去推算这个系统每秒种的并发量,然后推算每秒钟的请求对内存空间的占用,进而推算出整个系统运行期间的JVM内存运转模型。然后通过各个参数调优,尽量让垃圾对象在年轻代被回收掉,避免频繁 Full GC。

下面就假定有一个每日百万交易的支付系统,来看看怎么估算一个比较合理的内存运转模型。

第1步:分析系统核心业务与核心压力

首先要分析出一个系统的核心压力集中在哪里,每日百万交易的支付系统,最核心的业务当属支付流程。每次支付请求将创建至少一个订单对象,这个订单对象包含支付的用户、渠道、金额、商品、时间等信息。

支付系统的压力有很多方面,包括高并发请求、高性能处理请求、大量订单数据存储等,但在JVM层面,这个支付系统最大的压力就是每天会在JVM中频繁的创建和销毁100万个支付订单对象。

第2步:预估每秒需处理多少次请求

要设置合理的JVM内存大小,首先要估算出核心业务每秒钟有多少次请求。假设每天100万个支付订单,一般用户交易都集中在每天的高峰期,也就是中午或晚上那3~4个小时,那么平均每秒就将近100次。

假设支付系统部署3台机器,那么平均到每台机器就30个支付请求。

第3步:估算一次请求耗时多久

用户发起一次支付请求,后端将创建一个订单对象、做一些关联校验、写入数据库等,还有一些其它操作,比如调用第三方支付平台等。假设一次支付请求耗时1秒吧,那么每秒钟就会产生30个订单对象,然后1秒后这30个对象就变为垃圾对象了。

第4步:估算每秒请求占多少内存

我们可以根据订单类中的实例变量类型来计算就可以了,比如 Integer 占4个字节,Long 占8个字节,String 类型根据长度来计算。假设一个订单类按20个字段来算,往大一点粗略估算占500字节吧。那么每秒30个支付请求就是 30 * 500B ≈ 15KB。

但实际上,每次请求的过程中,除了订单对象,往往还会创建大量其它类型的对象,比如其它的一些关联查询对象,Spring框架创建的对象等,这时一般需要对单个对象放大10~20倍。

而且支付系统还会包含其它的一些业务,比如交易记录、对账管理、结算管理等,再扩大个5~10倍。这样算下来每秒钟基本会产生1M左右的对象。

但这些也不是绝对的,对于一些特殊的系统,比如报表系统、数据计算系统,每次请求创建的对象可能超过10几M了,那么附属创建的这些对象可能影响就没那么大了,此时可以考虑忽略不计。

第5步:估算元空间大小

元空间主要是存放类型信息,也没什么太多好调优的,一般设置几百M够用就可以了,比如256M。

第6步:估算栈内存大小

线程栈主要就是运行期间存储方法的参数、局部变量等信息,一般设置1M就足够了。比如系统有100个线程,那么虚拟机栈就会至少占用100M内存。

第7步:内存分配

这个每日百万交易的支付系统部署3台机器,每台机器每秒扛30个请求。假设部署的机器是2核4G,但是机器本身运行还需要一些内存,那么JVM就只分2G,考虑到要给元空间、虚拟机栈预留空间,那假设堆内存只分1G,新生代给500M,老年代给500M,那 Eden 区就占400M,两个 Survivor 区各占50M。

这样估算下来,就是如下的内存参数设置:

-Xms1G -Xmx1G -Xmn500M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:SurvivorRatio=8

第8步:系统运转模型

经过上面的分析,再结合机器配置,我们就能大致估算这个系统的内存运转模型了。使用上面的内存设置,那么每秒接收30个请求,在Eden区创建30个订单相关的对象;将产生1M新对象,1秒后请求处理完成,将产生1M的垃圾对象;将在400秒后,也就几分钟的时间,Eden 区就占满了,然后触发 Young GC;YoungGC时会把存活对象复制到FromSurvivor区,然后回收掉新生代的垃圾对象,如此往复。如果Survivor区分配不合理,导致存活对象进入老年代,还可以估算出多久触发一次FullGC/OldGC。主要就是估算出GC的频率,然后就可以对内存进行调优了。

第9步:瞬时压力增加时的模型估算

如果遇到搞大促活动或一些突发的性能抖动,压力可能瞬间增加10倍甚至更多,那每秒可能就是上千笔支付请求,每秒内存占用至少10M以上了。这个时候每次支付请求可能就不是1秒能处理完的了,因为压力骤增,系统内存、线程资源、CPU资源都将打满,导致系统性能下降,这样可能有些支付请求需要耗时好几秒,那可能就有几十M对象会占用堆内存几秒钟。

还是按照2核4G的机器部署,堆内存设置1G,新生代500M,Eden区400M,Survivor50M。这时Eden区只需几十秒就满了,然后触发YoungGC。但是,因为压力增加,有些请求需要好几秒,就会有几十M对象会将无法被回收,就被复制到 Survivor 区。

这时就有多种情况了,首先存活几十M的对象可能大于Survivor区50M的内存,那么就会直接复制到老年代。然后如果小于Survivor区,也大于了Survivor区50%的空间了,下一次通过动态年龄规则判断也可能会将部分对象复制到老年代。

然后经过大概10几次YoungGC,也就几百秒后老年代也快满了,这时可能就会触发FullGC,FullGC时要暂停系统运行,无法处理任何请求,而且这种情况下老年代大部分都是垃圾对象,回收性能是很低的。

回到顶部

三、YoungGC 调优

1、合理分配内存降低YoungGC频率

根据前面的估算,在正常的情况下如果给堆分配1G的空间,会频繁触发 YoungGC,新生代回收虽然效率高,但也会 Stop The World,暂停系统运行,如果频繁YoungGC,就会频繁暂停系统。

我们可以考虑增大新生代内存,同时使用内存大一点的机器,比如使用4核8G,那么JVM分4G,给堆空间分配3G,新生代给1.5G,老年代给1.5G,Eden 区差不多1.2G,Survivor区150M,这个时候Eden区差不多要半个小时才会占满,然后触发一次YoungGC,而其中99%都是垃圾对象,采用标记-复制算法基本上很能就能完成YoungGC,这就大大降低了YoungGC的频率。

如果业务量更大,还可以考虑横向多部署几台机器,这样分到每台机器的请求就更少了,压力也更小。

2、保证Survivor空间足够

如果遇到大促活动,瞬时压力增大,每秒就会有10M以上的对象产生,然后有几十兆甚至上百兆的对象会存活几秒以上。按照前面的内存模型来分析下,那 Eden 区2分钟左右就会占满ÿ

JVM性能调优(3)——内存分配和垃圾回收调优相关推荐

  1. JavaScript内存分配及垃圾回收机制

    JavaScript内存分配及垃圾回收机制 简介 像C语言这样的高级语言一般都有底层的内存管理接口,比如 malloc()和free().另一方面,JavaScript创建变量(对象,字符串等)时分配 ...

  2. JVM内存分配与垃圾回收浅析

    为什么80%的码农都做不了架构师?>>>    想做architect,就必须对JVM的性能有所了解.JVM的内存管理是性能的一大瓶颈.JVM的性能调优,必须建立在对内存管理策略理解 ...

  3. python的内存调优_python内存机制与垃圾回收、调优手段

    一.python的内存机制 python中的内存机制 如下所示: _____ ______ ______ ________ [ int ] [ dict ] [ list ] ... [ string ...

  4. JVM结构、内存分配、垃圾回收算法、垃圾收集器。

    2019独角兽企业重金招聘Python工程师标准>>> 一.JVM结构 根据<java虚拟机规范>规定,JVM的基本结构一般如下图所示: 从左图可知,JVM主要包括四个部 ...

  5. JVM内存分配与垃圾回收

        其实已经有很多大牛在这方面做了很好的介绍,我在这篇文章里讲下我自己的一些理解,受限于我的认知水平,可能不一定正确,请自我甄别. JVM的GC自动垃圾回收器是JAVA的一大特色,垃圾回收器要解决 ...

  6. Java内存分配与垃圾回收(二)

    写在前面:主要为<深入理解Java虚拟机>的读书笔记,加上自己的思考,本篇主要讲垃圾回收,图片主要来自网络,侵删. Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的" ...

  7. java内存分配和垃圾回收,Java内存分配与垃圾回收

    1.JVM管理的内存包含下图所示的几个运行时数据区域,其中方法区和堆为线程共享的数据区域,程序计数器,虚拟机栈以及本地方法栈为线程私有的数据区域. 程序计数器:可以看做是当前线程所执行的字节码的行号指 ...

  8. java内存分配和垃圾回收_深入理解java虚拟机(二)垃圾收集器与内存分配策略...

    垃圾收集器与内存分配策略 垃圾收集,三个步骤 什么时候收集,收集那些,怎么收集 1.收集那些 我们会将一些不使用的对象进行收集,进行回收内存空间,我们怎么知道呢 1.引用计数法 如果这个实例被其他地方 ...

  9. jvm内存模型与垃圾回收

    *JVM历史JIT编译(just-in-time compilation)狭义来说是当某段代码即将第一次被执行时进行编译,因而叫"即时编译" 互联网-js人工智能-python微服 ...

  10. 【转】Java内存与垃圾回收调优

    要了解Java垃圾收集机制,先理解JVM内存模式是非常重要的.今天我们将会了解JVM内存的各个部分.如何监控以及垃圾收集调优. Java(JVM)内存模型 正如你从上面的图片看到的,JVM内存被分成多 ...

最新文章

  1. 云计算时代的数据库运行
  2. 字符串类型的数字比较大小_Python核心知识系列:数字与字符串类型
  3. 批处理获取exe返回结果
  4. Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO)
  5. python生成范围内随机数_python在一个范围内取随机数的方法是什么
  6. SQLite内部机制和新特性
  7. c语言如何调用外部文件的函数调用,keil 中如何调用其他文件的函数
  8. IOS 正则表达式匹配文本中URL位置并获取URL所在位置(解决连接中文问题)
  9. 每周荐书:Kotlin、分布式、Keras(评论送书)
  10. 服务器地图不显示图片,传奇小地图不显示怎么办 传奇服务端小地图制作教程...
  11. 在线翻译转换器对接百度翻译、有道词典和谷歌翻译api
  12. 全景图拍摄方式有哪些?全景图拍摄制作流程是什么?
  13. 视频演示SHAtter越狱iOS 4.1
  14. HPnbsp;Jetdirectnbsp;打印服务器配置
  15. SpringBoot源码解析(十一)自定义banner
  16. 滴滴:去年协助警方破获25案件 成立打击黑产专项组
  17. 关于压缩感知的第一篇论文解析压缩感知研究新思路
  18. win7系统 (32位)安装包
  19. 关于python浮点数类型错误的是_关于Python的数字类型,以下选项中描述错误的是...
  20. seo搜索引擎优化新手详细操作教程

热门文章

  1. 国有土地使用证丢失还可以补办吗
  2. 使用python实现斐波那契数列的四种方法
  3. Oracle中通过Function,存储过程,触发器,调用实现解析Clob字段中存在的xml字符串
  4. 【Linux】静态库和动态库的理解
  5. 抖音舆情管理实施方案
  6. SQLAlchemy【复习】
  7. LGD的广州OLED项目再受挫,OLED电视已错失时机
  8. 百亿诈骗案频出,欧科云链用“技术责任”拓宽Web3安全边界
  9. Lunatic Never Content
  10. Docker安装篇(一)