高手的存在,就是让服务10亿人的时候,你感觉只是为你一个人服务......

JAVA性能分析之火焰图

目录
  1. 1. 安装环境
  2. 2. 安装lightweight-java-profiler
    1. 2.1. 解压lightweight-java-profiler
    2. 2.2. 修改globals.h [可使用默认配置]
    3. 2.3. 编译
    4. 2.4. 配置JVM参数,启动应用
    5. 2.5. 收集采样数据
  3. 3. 生成火焰图

JAVA火焰图可以方便的找到哪些代码消耗CPU,对性能分析和调优提供很大帮助。


安装环境

  1. jdk版本: openjdk-1.8.0_92 (只支持hotspot的vm)
  2. Centos 64位操作系统
  3. 安装了4.6以上版本的gcc
1
yum install gcc-c*
  1. 配置JAVA环境变量
1
2
3
4
5
编辑 /etc/profile文件
export JAVA_HOME=/opt/wildfly/openjdk/openjdk-1.8.0_92
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
记得执行source /etc/profile命令,使之生效。

安装lightweight-java-profiler

需要下载lightweight-java-profiler进行编译。 这里提供我的百度云盘下载。

解压lightweight-java-profiler

1
tar -xvf lightweight-java-profiler-master.war

修改globals.h [可使用默认配置]

有几个采样参数存于/lightweight-java-profiler-master/src/globals.h文件中,编译之前可做修改。

1
2
3
4
5
6
7
8
9
10
11
// 采样的频率,缺省是每秒100次 
static const int kNumInterrupts = 100;

// 最大采样的线程栈,缺省3000,超过3000就忽略
static const int kMaxStackTraces = 3000;

// 栈的深度,缺省是128(对于调用层次深的应用需要调大)
static const int kMaxFramesToCapture = 128;

// 采样数据保存至traces.txt文件中.
static const char kDefaultOutFile[] = "traces.txt"

编译

1
make BITS=64 all

执行成功后会生成build-64文件夹,里面有名为liblagent.so的文件。这就是收集profile数据的.so文件。

配置JVM参数,启动应用

在JAVA应用启动参数中加入:

1
-agentpath:${path}/liblagent.so

收集采样数据

traces.txt文件默认会在启动命令当前目录下生成(比如我使用的wildfly8,在启动目录/wildfly/bin目录下生成该文件)。

应用运行过程中traces.txt不会即时记录数据,在应用shutdown时才写入,所以不可kill进程,否则收集不到数据。


生成火焰图

火焰图需要使用FlameGraph工具进行转换。

1
2
cd FlameGraph
./stackcollapse-ljp.awk < ${path}/traces.txt | ./flamegraph.pl > {$path}/traces.svg

得到一个火焰图的.svg文件,用浏览器打开就可以看到火焰图了。

Alt text

在看火焰图的时候,x轴横条宽度来度量时间指标,y轴代表线程栈的层次,越宽代表占用的CPU时间越多,也就越是性能瓶颈。