[译]Java火焰图

标签: Java | 发表时间:2016-08-10 14:07 | 作者:
出处:http://colobu.com/

在我的前一天转的一篇文章中( [转]go's march to low latency gc),Twitch的Rhys Hiltner使用火焰图(FlameGraph)来分析Go程序的性能给我留下了深刻的印象,它使用Brendan Gregg创建的 火焰图工具生成直观的图像,很方便的分析Go的各个方法占用的CPU的时间。

因为我的一部分时间还是使用Java开发,所以就想到有没有Java相关的工具生成火焰图呢?答案当然是肯定的,而且它更早的应用于Java程序的性能分析。

火焰图工具的作者Brendan Gregg专门写了一篇文章: Java Flame Graphs,介绍如何生成火焰图的。这就是本文要翻译的文章。

Netflix深度使用了火焰图工具,他们专门写了一篇文章 Java in Flames,介绍他们是如何使用的,而且前段时间他们又写了一篇文章: 如何使用火焰图分析性能,每天为Netflix节省一千三百万分钟的计算时间,文中介绍了他们如何使用火焰题找到耗时的问题所在,为公司节省了大量的时间和金钱。(Brendan Gregg就是Netflix的员工,他的站点觉得是一个值得阅读的地方,还有很多其它性能相关的专题,比如Linux性能工具 http://www.brendangregg.com/linuxperf.html)

既然火焰图这么有效,你难道不想了解一下吗?

以下是Brendan Gregg文章的翻译。

Java火焰图是一个新的方法来可视化CPU的使用情况,本文中我会展示如何使用免费开源的工具来创建它:Google的 lightweight-java-profiler 以及我的 火焰图工具。希望有一天火焰图能成为所有的Java Profiler工具的标准特性,就像现在的调用图(call tree graph)一样。

更新信息(2015年8月) Netflix的博客的文章 Java in Flames展示了最新的最好的产生Java火焰图的方法,使用 Linux perf_events来一起显示Java和系统代码(system code paths)。我也在 Java CPU Flame Graphs一文中做了介绍。本文仅分析Java相关的方法,包含一些这些链接中的警告(caveats)。

下图显示了使用vert.x实现的一个简单的JavaScript的大图:



惊艳! 鼠标放上去还能看细节。它是SVG格式的。

Y轴是栈的深度(stack depth),X轴是所有的采样点的集合,每个方框代表一个栈帧(stack frame)。 颜色没有意义,只是随机的选取的。左右顺序也不重要。

你可以从最宽的帧看起,从底往上看,帧上的分叉代表不同的代码路径。我的文章 CPU flame graphs有很详细的解释,这个PPT flame graphs presentation 中业余介绍。一旦你掌握这些窍门,你可以快速识别和量化的CPU使用率。

左边最高的高是Mozilla Rhino JavaScript engine,它吃掉了 42.70% CPU (可以查看最低部的mozilla frame; 百分比包含它上面所有的子帧)。Java/vert.x 不需要运行这个引擎,释放这些CPU资源的话,可以增加大约一倍的性能。

其它的细节也很有趣:其它最大的CPU占用是 write0(), 大约31.99%, 这是可取的 – vert.x要响应请求,发送response。处理调优write0,要想提升性能,就得检查和减少其它代码的CPU占用。移除Rhino是最好的提升方法。

通过收集不同天的或者不同版本的火焰图,你可以快速地比较它们的性能,提供量化的数据。

Profile 数据收集

火焰图可以将采样的正在CPU上运行的栈信息可视化。你可以使用任意的可提供给你stack trace的profiler工具,我最开始使用hprof进行采样,但是发现它有些 问题

在这个例子中我使用Jeremy Manson开发的 lightweight-java-profiler 。它是一个精确的profiling技术的开源演示版本,并不是一个产品级的产品,所以需要一些手工操作,以下是我的步骤:

1、下载软件

     
1
2
     
svn checkout http://lightweight-java-profiler.googlecode.com/svn/trunk/ lightweight-java-profiler-read-only
cd lightweight-java-profiler-read-only

2、修改Makefile

我使用vi编辑Makefile,设置BITS为64, 并且为我的系统增加include路径`。 我的改变如下:

     
1
2
3
4
5
6
7
8
     
4c4
< BITS?=32
---
> BITS?=64
49c49
< INCLUDES=-I$(JAVA_HOME)/$(HEADERS) -I$(JAVA_HOME)/$(HEADERS)/$(UNAME)
---
> INCLUDES=-I$(JAVA_HOME)/$(HEADERS) -I$(JAVA_HOME)/$(HEADERS)/$(UNAME) -I/usr/include/x86_64-linux-gnu

3、编译软件

     
1
     
make all

4、设置agent
在运行Java程序的时候我加上了下面的设置:

     
1
     
-agentpath:/usr/local/lightweight-java-profiler-read-only/build-64/liblagent.so

Java开始运行时采样开始,程序结束时采样结束,采样数据会写入到traces.txt文件中,类似hprof的格式。火焰图工具会读取这个文件。

当然运行这个采样会有些开销,对于我的程序来说可以忽略不计(~1% 请求速率的降低,7%CPU的增长), 但是你的情况可能会不同。稍后会介绍如何检查采样速率。

火焰图

现在将traces.txt处理成火焰图:

     
1
2
3
     
git clone http://github.com/brendangregg/FlameGraph
cd FlameGraph
./stackcollapse-ljp.awk < ../traces.txt | ./flamegraph.pl > ../traces.svg

stackcollapse-ljp.awk是一个awk脚本,可以转换lightweight-java-profiler的输出为火焰图工具所需的格式(每栈一行)。 flamegraph.pl脚本有一些选项设置(-h查看选项列表),可以定制输出,包括改变标题。

现在可以在浏览器中打开traces.svg文件。

定制profiler

值得注意的是你可以配置lightweight-java-profiler的一些选项,打开src/globals.h文件:

     
1
2
3
4
5
6
7
8
     
// Number of times per second that we profile
static const int kNumInterrupts = 100;
// Maximum number of stack traces
static const int kMaxStackTraces = 3000;
// Maximum number of frames to store from the stack traces sampled.
static const int kMaxFramesToCapture = 128;

我可能倾向将采样速率从每秒100次降到50次,甚至更低,尤其是当我想长时间搜集数据的时候。我也会增大最大栈帧数,这样火焰图就能显示全栈信息。

Richard Warburton也写了一个profiler: honest-profiler,也是建立在相同的全精确性能分析技术之上(accurate profiling technique),就像lightweight-java-profiler一样,你也需要自己编译才能使用。

这些profiler只是查看Java内部的性能,我理想的profiler应该包含用户栈信息和内核栈信息,这能让我们集可以分析JVM GC的代码路径,也可以分析其它的JVM内部的性能以及内核的性能。

火焰图已经在其它领域证明了它的用处,包括内核的性能,Node.JS, Ruby, Perl等等, 可以查看我的 更新章节以了解最新的信息。


参考文档

以下是译者增加的其它参考资料:

相关 [java 火焰] 推荐:

[译]Java火焰图

- - 鸟窝
在我的前一天转的一篇文章中( [转]go's march to low latency gc),Twitch的Rhys Hiltner使用火焰图(FlameGraph)来分析Go程序的性能给我留下了深刻的印象,它使用Brendan Gregg创建的 火焰图工具生成直观的图像,很方便的分析Go的各个方法占用的CPU的时间.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

蜡烛火焰中发现纳米钻石颗粒

- 微笑!?~ - Solidot
根据发表在英国《化工通讯》杂志的报告,英国华人学者周午纵和同事发现,在蜡烛火焰中存在着纳米级钻石颗粒,将来可能发现较低成本生产钻石的途径. 英国圣安德鲁斯大学化学系教授周午纵想出了一个方法,研究小组的苏梓学博士进行了实验,结果发现,火焰中含有碳的所有四种形态,即无定形碳、石墨、富勒烯和钻石. 人们知道,在蜡烛火焰底部是碳水化合物,火焰顶部的产物是二氧化碳,而对火焰之中发生了什么,细节并不清楚.

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees [email protected] 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.

Java浮点数

- d0ngd0ng - 译言-电脑/网络/数码科技
Thomas Wang, 2000年3月. Java浮点数的定义大体上遵守了二进制浮点运算标准(即IEEE 754标准). IEEE 754标准提供了浮点数无穷,负无穷,负零和非数字(Not a number,简称NaN)的定义. 在Java开发方面,这些东西经常被多数程序员混淆. 在本文中,我们将讨论计算这些特殊的浮点数相关的结果.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.

java 验证码

- - ITeye博客
// 创建字体,字体的大小应该根据图片的高度来定. // 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到. // randomCode用于保存随机产生的验证码,以便用户登录后进行验证. // 随机产生codeCount数字的验证码. // 得到随机产生的验证码数字. // 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同.

Java异常

- - CSDN博客推荐文章
“好的程序设计语言能够帮助程序员写出好程序,但是无论哪种语言都避免不了程序员写出坏的程序.                                                                                                                          ----《Java编程思想》.

java面试题

- - Java - 编程语言 - ITeye博客
 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面. 抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节. 抽象包括两个方面,一是过程抽象,二是数据抽象.  继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法. 对象的一个新类可以从现有的类中派生,这个过程称为类继承.

Java使用memcached

- - 互联网 - ITeye博客
首先到 http://danga.com/memcached下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分别解压后即可. 然后是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后,进入其目录,然后运行如下命令:c:>;memcached.exe -d install
c:>memcached.exe -l 127.0.0.1 -m 32 -d start.