APP下载

Java效能分析利器-火焰图

消息来源:baojiabao.com 作者: 发布时间:2024-06-01

报价宝综合消息Java效能分析利器-火焰图

火焰图简介

Brendan D. Gregg 发明了火焰图。是通过收集系统核心的跟踪事件,把核心的CPU 内存、IO事件采集资料,最终来画出图。官方网站:http://www.brendangregg.com/overview.html

软件的效能分析,往往需要检视 CPU 耗时,了解瓶颈在哪里。可以针对优化;整个影象一火山,所以叫火焰图,每一层是一个方法栈,山越高说明方法栈多,呼叫层越多,火焰就越的颜色就越深。横轴并不是按时间顺序排的,一般是方法的字母排序。

我们关注的横轴和高度,横向越宽说明方法呼叫的次数越多。需要找的是从底部开始看,找那种平顶的山,这种山优化就是减少呼叫次数,减少呼叫所花的时间。这就是优化的方向与目标。

何为系统性能

系统性能分析是所有计算机使用者的一项重要技能,无论您是想了解膝上型电脑的速度慢,还是优化大规模生产环境的效能。它是对操作系统(核心)和应用程序效能的研究,但也可以为特定语言或应用程序带来更专业的效能主题。

这样做有两个一般原因:

提高性价比:特别是对于大型环境而言,即使很小的效能优势也可以大大节省IT支出。减少延迟异常值:对于任何大小的环境,偶尔的高延迟I / O都会降低应用程序请求速度,从而导致客户不满意。系统性能的其他活动包括系统评估的基准测试,容量规划,瓶颈消除和可扩充套件性分析 - 以便您及早发现可扩充套件性限制因素,并及时修复它们.

火焰图的作用

以前我们很难从源代码中直接找出程式效能的瓶颈,只能简单打印,或者靠经验来猜测。我们可以找到哪个方法是热程式码,呼叫栈的情况,直接优化热点程式码。能更好的提升系统性能。

火焰图的含义

X轴:表示抽样数,抽样到的方法就会显示,X轴越长只是说明在单位时间呼叫的次数比较多,并不说明方法执行的时间比较长。Y轴:表示程式码的呼叫栈,每一层就是一个呼叫栈,火焰越高呼叫栈越多,颜色也就越深。

常见的火焰图:

On-CPU,Off-CPUMemoryHot/ColdDifferential 等等。

On/Off-CPU 火焰图

On-CPU:执行绪花时间在CPU上执行。Off-CPU:在I / O,锁定,定时器,分页/交换等时阻塞等待的时间。

火焰图生成

第一步是资料采集,第二步生成火焰图,最后分析火焰图。

基础安装准备确保安装git、jdk、perl、c++编译器;

sudo apt-get install git openjdk-8-jdk g++ -y

2.下载工具程式码。async-profiler FlameGraph用作Java程式效能资料采集

git clone https://github.com/jvm-profiling-tools/async-profiler

cd async-profiler/

make

把采集的资料生成svg检视

git clone https://github.com/brendangregg/FlameGraph

3.准备Java程式码

测试ArrayList的操作:新增、插入、删除、遍历的速度

public class TestArrayList {

static int n = 100000;

public static void main(String[] args) {

try {

Thread.sleep(30000);

} catch (InterruptedException e) {

e.printStackTrace();

}

ArrayList data = testAdd();

testRead(data);

data.clear();

testInsert(data);

testRemove(data);

}

public static ArrayList testAdd() {

ArrayList data = new ArrayList(n);

for (int i = 0; i data.add(String.valueOf(i));

System.out.println("List add:" + i);

}

return data;

}

public static ArrayList testInsert(ArrayList data) {

for (int i = 0; i data.add(0, String.valueOf(i));

System.out.println("List insert:" + i);

}

return data;

}

public static void testRemove(ArrayList param) {

List data = Collections.synchronizedList(param);

Iterator it = data.iterator();

while (it.hasNext()) {

String next = it.next();

it.remove();

System.out.println("List remove:" + next);

}

}

public static void testRead(ArrayList data) {

for (int i = data.size() - 1; i >= 0; i--) {

data.get(i);

System.out.println("List read:" + i);

}

}

}

效能指令码:

jps | grep TestArrayList |awk '{ print $1}' | ./profiler.sh -d 120 -o collapsed -f /Users/ttylang/gitee/async-profiler/ArrayList.txt `xargs`

perl flamegraph.pl --colors=java ~/gitee/async-profiler/ArrayList.txt > Arraylist.svg

ArrayList的插入的删除的成本是jbb高的,而插入效能成本比删除还要略高。

测试LinkedList的操作:新增、插入、删除、遍历的速度

public class TestLinkList {

public static void main(String[] args) {

try {

Thread.sleep(30000);

} catch (InterruptedException e) {

e.printStackTrace();

}

LinkedList data = testAdd();

testRead(data);

data.clear();

testInsert(data);

testRemove(data);

}

public static LinkedList testAdd() {

LinkedList data = new LinkedList();

for (int i = 0; i data.add(String.valueOf(i));

System.out.println("LinkList add:" + i);

}

return data;

}

public static void testInsert(LinkedList data) {

for (int i = 0; i data.add(0, String.valueOf(i));

System.out.println("LinkList insert:" + i);

}

}

public static void testRemove(LinkedList param) {

Iterator it = param.iterator();

while (it.hasNext()) {

String next = it.next();

it.remove();

System.out.println("List remove:" + next);

}

}

public static void testRead(LinkedList data) {

for (int i = 0; i data.get(i);

System.out.println("LinkList read:" + i);

}

}

}

jps | grep TestLinkList |awk '{ print $1}' | ./profiler.sh -d 120 -o collapsed -f ./Users/ttylang/gitee/async-profiler/ArrayList.txt `xargs`

perl flamegraph.pl --colors=java ~/gitee/async-profiler/LinkList.txt > Linklist.svg

从图上可看出LinkedList这种遍历方式是要命的,其他方法效能采集只有一个新增,其余方法几乎没有采集到,我还测试了好几遍,还以为是出错了。

2019-10-24 01:56:00

相关文章