写点什么

JVM 性能调优,分享些好用的内存分析神器

作者:Steven
  • 2023-02-10
    河南
  • 本文字数:2070 字

    阅读完需:约 7 分钟

对于高并发访问量的电商、物联网、金融、社交等系统来说,JVM 内存优化是非常有必要的,可以提高系统的吞吐量和性能。通常调优的首选方式是减少 FGC 次数或者 FGC 时间,以避免系统过多地暂停。FGC 达到理想值后,比如一天或者两天触发一次 FGC。FCT 时间优化为 100~300 毫秒后,再减少 YoungGC 次数或者 YoungGC 时间,YoungGC 仍然会消耗 CPU 资源,优化 YoungGC 调用次数和消耗的 CPU 资源,可以提高系统的吞吐量。

优化 GC 前,必须获取 GC 的实际使用情况,最好的方式是通过 GC Log 收集垃圾回收日志,通过一些可视化工具查看垃圾回收分析数据,比如 GCEasy。持续优化和对比优化前后的 GC Log,能确认吞吐量和性能是否得到提升。

下面看看几个常用的内存分析命令和工具


jstat 命令


JDK 自带的 jstat 命令用于查看虚拟机垃圾回收的情况,如下命令使用 gcutil 参数输出堆内存使用情况统计:


jstat –gcutil  -h 20 pid 1000 100


此命令显示进程为 pid 的内存使用汇总,1000 毫秒输出一次,总共输出 100 行。-h 20 表示每 20 行输出一次表头。-gcutil表示显示 JVM 内存使用汇总统计:


列表显示了虚拟机各个代的使用情况,描述了堆内存的使用占比和垃圾回收次数,以及占用时间,具体含义如下:

  • S0,第一个幸存区使用比值。

  • S1,第二个幸存区的使用率。

  • E,伊甸园区的使用比值。

  • O,老年代。

  • M,方法区、元空间使用率。

  • CCS,压缩使用比值。

  • YGC,年轻代垃圾回收次数。

  • YGCT,年轻带垃圾回收占用时间。

  • FGC,全局垃圾回收次数,这对性能影响至关重要。

  • FGCT,全局垃圾回收的消耗时间。

  • GCT,总的垃圾回收时间。

可以看到 S0、S1、E 变化频率高,说明程序在频繁创建生命周期短的对象,FGC 为 0,表示还未做过全局垃圾回收。如果 FGC 变化频率很高,则说明系统性能和吞吐量将下降,或者可能出现内存溢出。


其他查看汇总信息的常用选项如下:

  • -gc,类似 gcutil,gcutil 以百分比形式显示内存的使用情况,gc 显示的是内存占用的字节数,以 KB 的形式输出堆内存的使用情况。

  • -gccause,类似 gcutil,额外输出 GC 的原因。


jmap 命令

jmap 命令用于保存虚拟机内存镜像到文件中,然后可以使用 JVisualVM 或者 MAT 工具进行进一步分析。命令如下:


jmap -dump:format=b,file=filename.hprof pid
复制代码


需要注意,实际系统会有 2GB 到 8GB 内存,此命令会导致虚拟机暂停工作 1~3 秒。还有一种是被动获取方式,当虚拟机出现内存溢出的时候,会主动“dump”内存文件。添加虚拟机启动参数:


-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof


当虚拟机判断达到内存溢出触发条件的时候,会有如下输出并保存镜像文件:

java.lang.OutOfMemoryError: Java heap spaceDumping heap to heapdump.hprof ...
复制代码


当获得镜像文件后,打开 JvisualVM 工具,选择菜单“File”,点击装入,选择我们保存过的 dump 文件,这时面板会打开内存镜像文件。打开较大的内存镜像文件需要较长的时间,需要耐心等候,其他工具,如 MAT,或者商业的 YourKit Java Profiler 打开镜像文件更快,分析功能更强大。


GCeasy


GCeasy 是一个分析 GC 日志文件的在线网站,能根据上传的 GC 日志,以图表形式显示 GC 回收过程和统计数据。下图显示的是 GC 性能的统计情况,如吞吐量显示为 99.935%,说明只有少量 CPU 资源用于垃圾回收。最长的 GC 时间是 20 毫秒,属于正常范围。在测试 JVM 参数调整是否能增加吞吐量,减小垃圾回收占用的 CPU 时,可以使用这个统计功能。



下图统计了 GC 总的时间和回收的字节数,也显示了 Full GC 的统计情况。


JMC


Java Mission Control 简称 JMC,是 JDK 自带的工具,是一个高性能的对象监视、管理、产生时间分析和诊断的工具套件,笔者主要用来追踪热点代码与热点线程,是主要的内存优化调优工具。

类似 JVisualVM,通过 JMX 连接进入 JMC 控制台。

通过连接到远程 JVM 进程后,可以执行飞行记录(FlightRecord),选择飞行记录存放的路径与执行时间即可,如下图所示。需要注意的是,执行飞行记录功能时会对当前 JVM 进程有一定的性能影响(大约为 5%~10%),所以建议 JMC 连接隔离环境中的服务器并执行飞行记录功能。



通过一段时间的记录,飞行记录可以反映线程的繁忙程度,以及 CPU 的热点方法。

使用热点方法可以直接找到最耗时的几个方法,对热点方法重点优化就可以使 CPU 的使用率下降一大截。

飞行记录还可以反映内存增长的热点方法,以及显示单位时间内创建的最多对象的方法。下图为找到的内存对象中创建的最多的char[]的方法,一个是 Fastjson,另一个是 Kryo。



小结:通过 JMC 的热点方法的统计结果可以有针对性地进行优化,笔者通过对线上系统进行优化使得 CPU 使用率下降了 40%、内存 GC 频率下降了 100%以上。

MAT

MAT 是Memory Analyzer的简称,它是一款功能强大的 Java 堆内存分析器,可以分析具有数亿个对象的内存镜像,快速计算对象大小,自动找到嫌疑的泄漏对象并形成内存泄漏报告。MAT 是基于 Eclipse 开发的,是一款免费的内存镜像分析工具,是笔者发现内存泄漏原因的主要工具。

通过File-Open Heap Dump可以打开内存镜像文件,显示内容如下图所示。



它提供了Leak Suspects 报告,输出有可能发生内存泄漏的对象。

OQL

OQL 语句类似 SQL 语句,可以在 VisualVM、MAT 等大多数内存镜像分析工具中执行,完成对象查找任务。

发布于: 刚刚阅读数: 4
用户头像

Steven

关注

还未添加个人签名 2023-01-09 加入

还未添加个人简介

评论

发布
暂无评论
JVM性能调优,分享些好用的内存分析神器_Steven_InfoQ写作社区