JVM 内存模型分析图像化

JVM 调优主要就是调整下面两个指标:

  • 停顿时间:垃圾收集器做垃圾回收中断应用执行的时间。-XX:MaxGCPauseMillis

  • 吞吐量:运行用户代码时间/(运行用户代码时间+垃圾收集时间)。-XX:GCTimeRatio=n

停顿时间越短就越适合需要和用户交互的程序,良好的响应速度能提升用户体验;高吞吐量则可以高效地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

GC调优步骤:

1)打印GC日志(注:Tomcat可以直接加载JAVA_OPTS变量里)
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc.log

2)分析日志得到关键性指标。这里注意,不同收集器的得到的日志不同(下面会逐一讲解)

3)分析GC原因,调优JVM参数。一般很少自己分析,现在都有现成的GC日志分析工具(比如 gceasy

1.GC调优实操

GC调优常用的可视化工具有 gceasy(国外网站)和 GCView(桌面应用),一般优先使用gceasy,但它如果被墙了就可以使用 GCView。这里主要就以Java默认的 Parallel收集器为示例进行调优。

1.1 通过gceasy分析GC日志

在 gceasy 中上传 GC 日志文件

注:关于怎么生成 GC 日志,这里就不说了,具体请参考 【JVM】GC(四):GC日志格式解析

在这里插入图片描述
在得到的数据中,最重要的就是如下两部分:堆内存情况和关键性能指标(吞吐量、停顿时间)

在这里插入图片描述
然后还可以看见 GC 的各项统计:

在这里插入图片描述
最后面就是关于GC原因的一个分析:

在这里插入图片描述
可以看到因为元数据区溢出,一共产生了四次GC,平均时间45ms,最长竟然达到了100ms。所以这里肯定是一个主要调优的点。

1.2 针对问题调优

那怎么调优呢?针对元空间下手!增大元空间大小,相关JVM参数” -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M

java -XX:MetaspaceSize=64M  -XX:MaxMetaspaceSize=64M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc-1.log -jar eureka-server.jar
  • 1

将调优后的gc日志(gc-1)放入gceasy进行分析:

在这里插入图片描述
结果如下,这里主要看吞吐量,停顿时间,young gc 和 full gc 次数

在这里插入图片描述
两次数据对比一下:

吞吐量平均停顿最大停顿Young gcFull gc
98.574%15.4 ms100 ms242
99.373%6.54 ms20 ms260

可以看到吞吐量已经到了一个很优秀的级别,并且没有了耗时最久的 full gc。

PS:这里其实还能给我们要给启示,为什么一个项目随着时间为什么启动越来越慢,可能就是元空间存在未回收对象,导致可用空间越来越小,启动时full gc次数多。


虽然程序的gc情况看着已经很好了,但是还有办法再进行优上求优吗?

full gc已经没有了,要再调优的话只能从minor gc入手了。

在这里插入图片描述
从gc文件中不难发现,gc之后常常伴随着扩容,那如果我把每次都扩容大一点,那么是不是就可以减少minor gc了。相关JVM参数是 -XX:YoungGenerationSizeIncrement,表示年轻代gc后扩容比例。

java -XX:YoungGenerationSizeIncrement=40 -XX:MetaspaceSize=64M  -XX:MaxMetaspaceSize=64M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc-2.log -jar eureka-server.jar
  • 1

在这里插入图片描述

1.3 G1收集器调优

这里再讲一下G1收集器的调优,像什么gceasy和扩容元数据区调优就不说了。G1的特别之处在于它拥有可预测模型,所他可以以参数形式设置目标吞吐量(-XX:GCTimeRatio=99)和停顿时间(-XX:MaxGCPauseMillis=100)。

java -XX:+UseG1GC -XX:GCTimeRatio=99 -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:./gc-g1.log -jar eureka-server.jar
  • 1

这里注意,99%的吞吐量已经属于一个比较苛刻的要求了,可预测并不是百分百,所以有可能加上这两个指标后,gc性能反而不如前…

更多G1调优方案,请参考G1官网建议,总结几点如下:

  • 不要手动设置新生代和老年代的大小,只要设置整个堆的大小

G1收集器在运行过程中,会自己调整新生代和老年代的大小 其实是通过adapt代的大小来调整对象晋升的速度和年龄,从而达到为收集器设置的暂停时间目标 如果手动设置了大小就意味着放弃了G1的自动调优

  • 不断调优暂停时间目标

一般情况下这个值设置到100ms或者200ms都是可以的(不同情况下会不一样),但如果设置成50ms就不太合理。暂停 时间设置的太短,就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续 的过程,逐步调整到最佳状态。暂停时间只是一个目标,并不能总是得到满足。

  • 使用-XX:ConcGCThreads=n来增加标记线程的数量

IHOP如果阀值设置过高,可能会遇到转移失败的风险,比如对象进行转移时空间不足。如果阀值设置过低,就会使标 记周期运行过于频繁,并且有可能混合收集期回收不到空间。 IHOP值如果设置合理,但是在并发周期时间过长时,可以尝试增加并发线程数,调高ConcGCThreads

  • MixedGC调优

-XX:InitiatingHeapOccupancyPercent
-XX:G1MixedGCLiveThresholdPercent
-XX:G1MixedGCCountTarger
-XX:G1OldCSetRegionThresholdPercent

2.GC常用参数

2.1 堆栈设置

-Xss:每个线程的栈大小

-Xms:初始堆大小,默认物理内存的1/64

-Xmx:最大堆大小,默认物理内存的1/4

-Xmn:新生代大小

-XX:NewSize:设置新生代初始大小

-XX:NewRatio:默认2表示新生代占年老代的1/2,占整个堆内存的1/3。

-XX:SurvivorRatio:默认8表示一个survivor区占用1/8的Eden内存,即1/10的新生代内存。

-XX:MetaspaceSize:设置元空间大小

-XX:MaxMetaspaceSize:设置元空间最大允许大小,默认不受限制,JVM Metaspace会进行动态扩展。

2.2 垃圾回收统计信息

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintGCTimeStamps

-Xloggc:filename

2.3 收集器设置

-XX:+UseSerialGC:设置串行收集器

-XX:+UseParallelGC:设置并行收集器

-XX:+UseParallelOldGC:老年代使用并行回收收集器

-XX:+UseParNewGC:在新生代使用并行收集器

-XX:+UseParalledlOldGC:设置并行老年代收集器

-XX:+UseConcMarkSweepGC:设置CMS并发收集器

-XX:+UseG1GC:设置G1收集器

-XX:ParallelGCThreads:设置用于垃圾回收的线程数

2.4 并行收集器设置

-XX:ParallelGCThreads:设置并行收集器收集时使用的CPU数。并行收集线程数。

-XX:MaxGCPauseMillis:设置并行收集最大暂停时间

-XX:GCTimeRatio:设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)

-XX:YoungGenerationSizeIncrement:年轻代gc后扩容比例,默认是20(%)

2.5 CMS收集器设置

-XX:+UseConcMarkSweepGC:设置CMS并发收集器

-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况。

-XX:ParallelGCThreads:设置并发收集器新生代收集方式为并行收集时,使用的CPU数。并行收集线程数。

-XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩

-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收

-XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收

-XX:+CMSIncrementalMode:设置为增量模式。适用于单CPU情况

-XX:ParallelCMSThreads:设定CMS的线程数量

-XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发

-XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理

2.6 G1收集器设置

-XX:+UseG1GC:使用G1收集器

-XX:ParallelGCThreads:指定GC工作的线程数量

-XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的幂),默认将整堆划分为2048个分区

-XX:GCTimeRatio:吞吐量大小,0-100的整数(默认9),值为n则系统将花费不超过1/(1+n)的时间用于垃圾收集

-XX:MaxGCPauseMillis:目标暂停时间(默认200ms)

-XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%)

-XX:G1MaxNewSizePercent:新生代内存最大空间

-XX:TargetSurvivorRatio:Survivor填充容量(默认50%)

-XX:MaxTenuringThreshold:最大任期阈值(默认15)

-XX:InitiatingHeapOccupancyPercen:老年代占用空间超过整堆比IHOP阈值(默认45%),超过则执行混合收集

-XX:G1HeapWastePercent:堆废物百分比(默认5%)

-XX:G1MixedGCCountTarget:参数混合周期的最大总次数(默认8)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值