“坚持性能测试——不要用你的眼睛去优化性能”
0x00. 前言
JVM和性能调优相关的知识很重要, 前置知识太多, 只能后续再补, 我也是且行且积累, 先直接先写了..
首先工具类产品千变万化, 但是归根到底就那几个派系, 所以我们优先选择掌握原生自带的, 社区活跃的, 功能强大的JVM工具, 以下是我简单分了三类, 都是很棒很好用的, 要会熟练使用, 实际的战斗中, 掌握这三类兵器是解决疑难问题的拿手武器:
- 可视化监控: 火焰图(必会) 、 JProfiler(推荐)、JConsole + Java VisualVM(原生已带)
- 原生命令: jstack、jmap、jhat、jstat (必会)
- 字节码热修改: Arthas (必会)
当然我对JVM和性能调优的理解也很浅薄, 可能还有不少好用/高级的方式没有了解过, 写文章很多时候就是秉持着”我为人人, 人人为我”的分享精神, 希望大家多多指教, ~
0x01. JVM参数
1. 修改JVM参数
10.23更新: 现在Arthas已经支持直接修改常见参数和查看了, 基本可以取代jinfo了, 详情参考文档
先说能动态修改的, 借助jinfo 命令, 可以热修改部分参数, 值得推荐.
1 | #首先看看哪些参数是可以动态修改的.以及他们目前的状态 |
可以看到下面有一些``PrintGC` 相关的参数, 这些对我们调优JVM很有用 ,试试动态打开.
1 | #注意有些参数是直接设置值的,但是bool的参数是通过参数名前的+/-表示开关 |
但是这有个很难受的事就是, 你发现有些时候你一通操作, gc日志实际完全没受到影响… 遇到jinfo不生效的话, 还是别用jinfo调了…
然后贴一个我综合了Cassandra官方+ElasticSearch官方jvm8.option 的G1GC配置 , 主要适用于存储/计算为主的底层组件[比如图] (机器内存 > 64G) ,解释参考
1 | # heap memory should < 32G because jvm's obj-pointer may be out of control (referrence ElasticSearch↑) |
待补充…
0x02. jstack
jstack主要涉及java线程相关的知识, 这个之后会单独补充一下, 先给个最常用的jstack使用方法 :
1 | #打印100次jstack, 然后每隔10条看一次. 如果时间间隔长,可以加比如 && sleep 10s |
然后打出了一堆jstack信息, 就是学会如何去看了.
待补充…
0x03.火焰图 (重点)
“ 童年时代,每逢冬天和家人围坐在火堆旁边烤火,我就不由想起了壁炉里熊熊燃烧的火焰的形态。火焰图也就是这样来的(:” —- 鲁迅
火焰首先从根燃起, 然后以火苗的形式往上面窜升. 把从靠近根到顶部的每个火苗,想象成一个调用栈, 由于火苗有许多根,这也就和进程执行逻辑相似了.
那进入正题, 火焰图需要重点掌握, 因为它是跨平台, 跨语言的性能分析利器. 适用于JS, C/C++, Python, Java, PHP, GO 等等语言, 并一般都有专用的版本, 而且在Unix 上可通用的监控某个进程PID来快速找到这个进程某段时间在做什么, 并生成一张可视化的SVG图, 从而帮助我们快速找到性能瓶颈. 关于火焰图的基本使用和普及参考:
然后原生的火焰图工具使用比较繁琐, 这里我们用的是在原生基础上做了封装和优化的Java专用版-async-profiler1.5 ,就很易用了.
Linux包下载到你需要监控的机器上, 不同于jstack 的100次踩点打印, 火焰图的主要是帮你找到程序运行(比如60s)期间, 整体上哪个方法耗时最长, 然后形成一个直观的图来展示(IDEA在Mac版上已经内置支持了), 细节分析则依靠”JProfile + Arthas”
最简单的使用就一条命令, 指定pid和监控的时间, 然后生成火焰图的路径, 并且如果程序提前终止了 ,这边也会自动停止, 需要注意的是, 不同实现的增强版火焰图里, 可能与原生的设计是稍有一些变化的, 例如火焰颜色可能就是有区别, 有意义的 (~~不能听风就是雨~~~), 比如下图中, 我观察推测(官方没找到具体说明)如下:
- 绿色: 代表java执行的代码 (主要)
- 黄色: 代表
C/C++一类的Native代码, 包括编译器/GC执行 (次要) - 红色: 代表系统调用层, 或是未知的执行代码段..
- 其他: 未知..
以上如果有官方的说法, 或者偏差的地方请及时告知, 多多指教~
更新: 找到了作者大大的详细来龙去脉说明, 并且写的非常的好.也举了很多例子和结合, 强烈推荐看看比如这个PDF分享, 这是对应blog, 下图选自作者另一PDF.
1 | #把60s内的进程请求转化为火焰图. |
然后实际的使用就需要结合具体的案例来说了. 比如程序更新了几个新功能后你发现GC次数/时间锐增, 或是内存占用明显变大, 又或是运行速度有明显下滑, 这些场景都非常适合同一环境下, 打两个火焰图对比, 一般就能很快找到思路. 而不是对着修改的几千行代码乱看, 没有头绪的去找到底哪里写的有问题..
更新: 典型实例和综合运用参考下一篇一次图Hugegraph-Loader性能问题的分析 ,当然进阶更建议的是参考作者的很多好的分享, 很多也有视频回放, 比我的思路肯定要好的多.
0x04. jmap
一般来说, 出现内存泄露相关的问题的时候, 就离不开使用jmap这个命令查看/导出当前的堆的具体使用情况, 然后再把堆文件丢给其他分析工具进行分析, 所以是必须得会用的.
1 | 最常见的三板斧: |
补充: 实际用法可参考一次内存泄露问题的解决过程.
0x05. JProfiler
JProfiler可以看做是”原生性能监控/分析 + MAT” 的综合加强版, 功能强大, 界面美观, 类似IDEA, 它本身是一个商业软件, 所以需要自己动手丰衣足食安装并与IDEA集成…. 后面说的内容都是基于**19年最新的Jprofile 11版本. (JDK 1.8), 这是软件的界面全览. 左侧前几个**是核心模块:
从上图中, 我们就能发现JProfiler到底关注哪几个方面 :
- 方法调用分析 : 实时分析包括时延, CPU/内存使用, GC细节等
- 内存分析: 离线/在线的分析堆内存中的 “对象 , 引用链 ,GC” , 帮助找到内存溢出/泄露的元凶, 在线分析可以优化内存使用.
- 线程分析: 对多线程和各种锁已经线程状态直观展示.
- 其他系统集成: 这也就是上图中后三个的体现, 比如Socket组件里连接最容易中断的点, Web服务里启动耗时最长的地方, DB里我想找出执行速度最慢的
SQL语句等. (不过我在想这个直接在db里复现不是更快么?)
了解了基本功能后, 再来看看整体架构:
初看可能除了UI 模块, 其他都是一脸懵逼, 所以强烈建议看图前, 先阅读一下这篇深入浅出JProfiler - 使用原理, 这里再简单说一下核心的几个模块:
1.Agent
关键点就是这个JProfiler Agent (现在这种方式也很流行), 不管是在本地还是远端, 它可以通过JVM启动的时候添加-agentpath:/path/to/libxx,xxx 来附着在JVM上, 成功后它会动态注入一些性能监控操作的字节码, 用以各种JVM参数监控
2.UI
比较好理解, 它负责把agent采集到的信息可视化展示. 要注意的是, 不管是本地还是远端, UI都是通过socket 与agent通信, 所以没有本质区别.
3.Command
除了可视化展示, JProfiler自身依靠一系列命令实现功能, 主要是控制agent进行各种操作(比如图上的jcontroller/jpdump等). 需要可参考官方文档.这不多介绍
这样整个JProfiler 我想从整体功能+结构上, 就有了一个比较直观的认识, 再来使用它就不会觉得很陌生. 不知如何下手了~ (也可以从类似的事中总结一些经验.)
然后我们定位线上问题, 多是使用JProfile远程连接, 同时需要下载Linux端的agent版, 用它”嵌入”到需要观察的JVM中, 然后通过本地的JProfile去获取agent的信息可视化展示. (顺带一提的是: Linux版解压后/doc/JProfiler.pdf 是很详细的官方文档, 推荐参考, 比网上搜索靠谱的多, 这是在线版)
配置好后, 就开始进入正题了, 首先agent有两种监控方式:
- (默认)Sampling : 在初用的时候你都可以用这个方式, 对性能影响小, 能收集大部分数据 (但不一定很精准, 也不能统计到很细的信息统计: 比如方法级别的)
- Instrumentation: 其实就是完整模式, 缺点是默认会显示所有类, 你需要自己配置过滤掉许多, 熟悉了之后应该都可以用这种模式.
6月13更新: 发现有个系列写的还不错, 虽然大部分是翻译的官方文档, 但是也很有参考价值, 想了解的同学可以先看这个, 后续我会结合具体的例子来讲, 因为原理分析耗时比较多, 可能暂时填坑比较慢.
未完待续…..
0x06. 其他工具
除了JVM相关和Linux相关的工具外, IDEA本身也有一些很好用的工具, 帮助我们提高开发效率, 比如著名的Cloud Toolkit :
它是做什么的呢? 看个官方对比图就很清楚了:
传统部署流程 (繁琐. 或需重度依赖
Drone/Jenkins类CI/CD工具)Cloud Toolkit流程 (适合个人开发 & 无CI/CD环境)
然后根据不同的服务器环境, 它提供了上图右侧对应的多种一键部署配置方案, 常见有三种:
第一次配置好后, 后面都是一键操作了, 而且就算你本地无法编译, 它也可以上传文件, 然后你在服务端自动编译打包分发
而且更为方便的是, 它内置了SSH-bash, 并自带了Arthas 这个强大的性能定位工具, 可以直接一键启动, 普通问题甚至不用单独启动
Xshell. 就能在IDEA里完成快速的问题定位 + 测试, 如官方下图所示:
注意事项 : 一键部署执行脚本/命令的时候, 有一些不能使用, CMD编写参考
7.25更新: 基于Linux的通用性能分析和监控拆分于此.






