
这是小小的第五篇
前言
在进行性能调优的时候,通常会借助性能分析工具,常用的性能分析工具有perf,DTrace,分析系统资源的使用情况,这些情况根据CPU,内存,生成相关的文本数据,这些文本数据不容易直接理解,所以采用火焰图进行分析。用图表的形式展示出来。本文将会展示具体实例。
火焰图
火焰图有不同的资源和事件类型,包括的主要数据有 CPU,Memory,Off-CPU,Hot/Cold。等等。下文中,所描述的火焰图指的是CPU的火焰图。
小方块 每个小方块代表一个函数,对应一个栈帧,小方块的宽度表示该函数在采样期间出现的频率,宽度越宽表示出现的频率越高。
栈帧 用于记录函数的活动记录,保存函数局部变量,函数参数等信息。因此想要分析函数调用堆栈关系,这里就需要使用采样得到栈帧信息。
Y 表示函数的调用栈,体现了stack深度,每个垂直方向的顶端小方块表示正在使用CPU的栈的深度。
X 表示采用数据的总量,X表示数据在对调用进行合并之后的结果。根据函数的字母顺序进行排列。X不代表使用CPU的长短,只是说明该方法出现的次数,宽度越宽表示该方法出现的次数越多。X可以直接作为CPU的时间长短。
生成火焰图
采样数据 -> 使用脚本生成 图解如下
工具
火焰图是根据任何包含stack traces 的 profile 数据生成,需要采集stack traces 数据, 列举如下的工具,采集相关的数据
Linux perf_events Mac DTrace and Instruments windows Xperf.exe
这里采用的是perf,在Linux系统下实验
安装
sudo yum install perf
生成数据
sudo perf record -F 99 -a -g -- sleep 30
此时会在当前目录下生成perf.data文件。
生成火焰图
sudo perf script | ./stackcollapse-perf.pl | ./flamegraph.pl > out.svg
会自动在当前目录下查找perf.data文件,然后生成svg文件。
然后会自动生成相对应的火焰图
Java混合模式火焰图
安装 perf
perf --version
安装perf-map-agent
安装gcc和gcc-c++
sudo yum install gcc
sudo yum install gcc-c++
安装cmake
sudo mkdir /home/q/perf-tools
cd /home/q/perf-tools/cmake-2.8.6
sudo ./configure --prefix=/home/q/cmake-2.8.6
sudo make && make install
安装perf-map-agent
git clone https://github.com/jvm-profiling-tools/perf-map-agent
cd /home/q/perf-tools/perf-map-agent
sudo /home/q/cmake-2.8.6/bin/cmake . && sudo make
配置Java选项
JDK >= Java 8 update 60 build 19
参数 **-XX:+PreserveFramePointer**
检查Jdk
java -version
检查JVM
ps wwp `pgrep -n java`|grep PreserveFramePointer --color
设置 -XX:+PreserveFramePointer
-Xms24g -Xmx24g -server -XX:+DisableExplicitGC -Dqunar.logs=$CATALINA_BASE/logs -Dqunar.cache=$CATALINA_BASE/cache -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGC -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=1 -Xloggc:$CATALINA_BASE/logs/gc.log -XX:+PrintSafepointStatistics -XX:ReservedCodeCacheSize=512m -XX:CMSInitiatingOccupancyFraction=50 -XX:+UseCMSInitiatingOccupancyOnly -XX:MaxTenuringThreshold=14 -XX:+PreserveFramePointer
安装FlameGraph
git clone https://github.com/brendangregg/FlameGraph.git
生成脚本
sudo ./gen-flame-graph.sh $SLEEP_SECONDS $PID
具体脚本内容
#!/bin/bash
SLEEP_SECONDS=$1
PID=$2
PERF_TOOLS_HOME=$(pwd)
GEN_RESULTS_DIR=$PERF_TOOLS_HOME/gen-flame-graphs-result
AGENT_HOME=$PERF_TOOLS_HOME/perf-map-agent
AGENT_JAR=$AGENT_HOME/attach-main.jar
AGENT_OUT=$AGENT_HOME/out
FLAME_GRAPH_PL_HOME=$PERF_TOOLS_HOME/FlameGraph
FLAME_GRAPH_GENERAGED_FILE=$PERF_TOOLS_HOME/flamegraph-mixed-model-`date +%Y%m%d-%H%M%S`.svg
MAP_FILE=/tmp/perf-$PID.map
function check_env(){
if [[ ! -x $JAVA_HOME ]]; then
echo "ERROR: JAVA_HOME not set correctly; edit $0 and fix"
exit
fi
if [[ ! -x $AGENT_HOME ]]; then
echo $AGENT_HOME
echo "ERROR: AGENT_HOME not set correctly; edit $0 and fix."
exit
fi
if [[ ! -x $GEN_RESULTS_DIR ]]; then
echo "ERROR: '$GEN_RESULTS_DIR' not found;Please mkdir a file :'$GEN_RESULTS_DIR'"
exit
fi
}
#generate perf.data with command: perf record
function perf_record(){
echo "Perf record for all processors with sleep 30 seconds."
cmd_perf="sudo perf record -F 99 -a -g -- sleep 30"
eval $cmd_perf
if [[ -e "./perf.data" ]]; then
echo "SUCCESS: perf.data was generated."
else
echo "ERROR: perf.data not generated;edit $0 and fix."
exit
fi
}
#agent mapping pid
function gen_map_file(){
user=$(ps ho user -p $PID)
echo "Agent mapping PID $PID with user $user"
cmd_agent="cd $AGENT_HOME;java -cp attach-main.jar:$JAVA_HOME/lib/tools.jar net.virtualvoid.perf.AttachOnce $PID"
cmd_agent="sudo -u $user sh -c '$cmd_agent'"
eval $cmd_agent
if [[ -e "$MAP_FILE" ]]; then
echo "generate map file"
chown root $MAP_FILE
chmod 666 $MAP_FILE
else
echo "ERROR: $MAP_FILE not created."
exit
fi
}
#generate flame graph
function gen_flame_graph(){
cmd_stack="sudo perf script|$FLAME_GRAPH_PL_HOME/stackcollapse-perf.pl --pid|$FLAME_GRAPH_PL_HOME/flamegraph.pl --color=java --width=800 --minwidth=0.5 --title="$PID flame graph" --hash > $FLAME_GRAPH_GENERAGED_FILE"
eval $cmd_stack
}
check_env
perf_record
gen_map_file
gen_flame_graph
echo "SUCCESS: generate flame graph."
使用脚本
改脚本是对Java进程的8708采样30s,生成flamegraph-mixed-model-date +%Y%m%d-%H%M%S.svg的Java混合模式火焰图
sudo ./gen-flame-graph.sh 30 8708
生成的图片

小明菜市场
推荐阅读
● 面试 | 从一个API缓存演化,详细了解Redis各项功能
● 实战 | Element UI 父子组件传值与事件绑定(逆向)
● 实战 | Element UI 父子组件传值与事件绑定(正向)


869

被折叠的 条评论
为什么被折叠?



