性能定位神器:Arthas

作者:微信小助手

发布时间:2023-10-23T09:51:40

之前,我们已经分享了一些关于实战方面的内容,有一些读者有给我留言,说这些内容对日常工作有帮助,这让我感到非常开心。

所以,今天我们继续来讲讲实战方面的内容,那就是:如何定位java程序中的性能问题?

这个话题来自于读者的留言,但无独有偶的是,我的日常工作也经常会碰到这个问题。我来介绍下我自己常用的一个方式,也算是一个实用小技巧,就是标题中的:使用Arthas来定位性能问题

你也许是这样来定位问题的



我相信大家或多或少都碰到过类似如下这样的问题:

有一个接口提供服务,但这个服务现在耗时很长,无法满足我们的要求,我们需要找到其中的性能问题并解决。

说白了,就是程序比较慢,我们要找到慢的地方。

最常见的办法无非是在代码各处添加打点逻辑,统计每一块代码的运行时间,类似下图这样:

这种办法有几个问题:

【1】打点的地方太多了,导致代码特别乱。

【2】容易漏了打点,导致关键位置没有分析到。

【3】很多时候会在线下环境打点分析,但是线下又没有足够的请求来复现性能问题。

【4】不是所有请求都会有性能问题,但打点针对所有请求,导致打点数据太多无法分析。

相信这些点很多同学都感同身受。一个性能分析花上几周都不见得能够定位到问题,更别谈解决了。

今天我给大家来介绍下如何使用Arthas来定位代码中的性能问题。也许无法解决所有问题,但“病急乱投医”的你用一下,搞不好就“瞎猫碰到死耗子了呗”

我这种说法好像是碰碰运气,但事实上在绝大部分场景下,Arthas可以帮助到我们的。我们这就开始吧。

01


Arthas是什么

用Arthas之前,我们还是要先介绍一下它。

Arthas是阿里巴巴开源的Java诊断工具,能够在线诊断Java应用程序的性能问题。它可以实时查看应用的线程、类、对象、方法等信息,并且支持热更新类和方法,还可以执行JVM命令和监控系统指标。此外,它还支持Spring Cloud应用、Dubbo服务等场景的诊断与治理,非常适合Java开发及运维人员进行Java应用程序的线上问题排查和性能优化。

我们看下其中的关键字:开源、Java、性能问题、热更新、JVM监控、线上问题排查

看到这些关键字,相信我已经不用做过多的介绍,你已经可以对Arthas的功能知道个八九不离十了。

我还是来再枚举下Arthas的功能:

【1】实时查看应用的线程、类、对象、方法等信息,支持热更新类和方法。同类工具参考:JConsole、VisualVM、YourKit。

【2】执行JVM命令,监控系统指标,如堆内存、GC、线程等。同类工具参考:jcmd、jstack、jmap等。

【3】支持Spring Cloud应用、Dubbo服务等场景的诊断和治理。同类工具参考:SkyWalking、Pinpoint、Zipkin等。

【4】实时监控请求的响应时间,打印出耗时最长的方法调用链。同类工具参考:Spring Boot Actuator、Micrometer等。

【5】追踪和分析方法的入参和返回值,支持 MVEL 等方式的表达式。同类工具参考:AspectJ、logback。

【6】支持 Java 8 lambda 表达式的调试和诊断。同类工具参考:Java Debugger、IntelliJ IDEA等。

02


如何使用Arthas诊断代码性能问题

01

基础诊断


我们还是用一个例子来说明。
下面这个controller提供了一个接口,从日志来看,这个接口耗时是174ms,我们需要确定其中耗时较长的部分。

最常规的办法就是上面提到的加上各种打点,我们再图示一下这种方式,如下:

可想而知,如果代码很多,其中的方法又层层嵌套的话,不知道要加多少打点代码了。

如果用Arthas的话,我们可以用它的trace命令来直接查看各个方法的耗时,我们一步步来做一下(这里我们省略了arthas的安装过程,非常容易):

【step1】启动我们的应用

第一步当然是先启动应用。

【step2】使用Arthas连接到我们的JVM进程

我们到arthas所在目录下,执行如下命令:

java -jar arthas-boot.jar

我们可以看到如下结果:

我们可以从中看到本地运行的所有jvm进程,从其中选择我们的程序【2】,输入2回车即可。

我们就进入了还蛮有腔调的Arthas工作台。

【step3】使用trace命令指定追踪的类和方法

接着我们输入要追踪的类和方法。输入格式为:trace {全限定类名} {方法名}

这里需要给Arthas点赞的是,整个类名和方法名的输入过程是可以使用tab来补全的,非常方便。

【step4】定位耗时部分

我们来访问下controller中的callServices这个方法。这个时候arthas控制台有如下输出:

我们可以看到,arthas给我们分析了整个过程中最耗时的部分。这不就是我们想要的功能吗?我们可以选择其中耗时的部分继续往下排查。

怎么往下?重新trace耗时的类名+方法名就好了。

就这样,我们找到了这个demo中耗时的部分,就是RpcC这个远程调用耗时过长。

要知道,这可以直接在不侵入代码逻辑的情况下,追踪性能的“凶手”。

02

进阶诊断


但在真实世界中,诊断可能没有那么简单,最常见的现象就是:并不是所有的请求都有性能问题,而往往是其中的一部分请求表现出了性能问题

在Arthas中,可以对需要观测的请求做筛选,以使得我们观测到我们关心的部分。

【根据入参筛选】

最常见的筛选条件就是根据入参进行筛选:

上图中,我们就要求:入参的第一个参数等于字符串“abc”才查看耗时情况。
上图红色框部分使用的是OGNL表达式,支持各种复杂的嵌套结构及比较逻辑,你可以自己去官网上了解下。

【根据耗时筛选】
还有一种较为常见的,就是我们只关心达到一定运行时间的情况,比如某个方法超过180ms我才关心其具体情况。那我们就可以使用#cost关键字。例如:

03


火焰图

最后,我们再来聊聊在碰到性能问题时我们常用到的一个工具,那就是“火焰图”。

火焰图并不是Arthas发明出来的东西,而Arthas中可以方便的采样并生成火焰图。我们来看一个例子(这个例子是上面我们讲述Arthas定位性能问题时用到的例子,这里再重新看一下 ):

从例子中可以看到,callServices接口调用了三个服务(ServiceA、ServiceB、ServiceC)。

然后,我们在Arthas中依次开启profile采集、观察采集样本数、终止采集(这里需要注意的是,profiler start默认对cpu采样,你也可以选择采样事件):

然后,我们打开采样后的火焰图(火焰图地址会在profiler stop后显示在终端)

简单说下火焰图怎么看:

【纵轴(Y轴)】表示的是方法调用的调用栈信息,即从最外层方法到最内层方法的调用信息。

【横轴(X轴)】表示的是方法调用的持续时间,即方法在执行过程中所占用的时间长度。

在一个火焰图中,越靠近下面的函数在x轴上越长是正常的,而越往上的函数就应该越短。所以,火焰图也像是一个个山峰。那么,如果火焰图出现较宽的峰顶,那就往往是性能瓶颈。

如上图所示,出现了明显的“平顶”。“平顶”对应的函数是ServiceC.process函数,我们看一下他的实现。

没错,这个ServiceC正是我故意实现的一个较为耗时的函数(计算1000w内的所有质数)。

所以,通过火焰图,我们找到了性能问题。

结语



到这里,我们把【如何使用Arthas定位java性能问题】讲完了。

事实上,Arthas远比今天介绍的要强大和丰富。这篇文章也算是Arthas的敲门砖,如果你感兴趣,非常推荐你自己去研究研究(Arthas的阿里云官网)。

回头说,性能问题是一个范围很广的问题。语言层面、算法层面、通信层面、部署层面等等都会有性能问题及对应的解决方式。我们今天仅聚焦在其中的一个小点,也就是定位java程序内的性能瓶颈。但我相信,这个点往往是我们工作中最常碰到和死磕的点。

希望今天的内容能够帮助到你,也推荐你收藏,如果以后碰到可以拿出来用用。

最后想要再叨叨两句我的【实战板块】。我对【实战板块】的要求是“小而美”。

所谓的【小】是指具备可操作性。你有某方面的问题,这篇文章足够帮助你动起手来就可以,并不追求多么全面。

所谓的【美】是指具备实用性。实战板块的内容就是针对日常工作的,不追求高大上的各种概念,接地气。

最后欢迎大家加入苏三的知识星球Java突击队,一起学习。

星球中有很多独家的干货内容,比如:Java后端学习路线,分享实战项目,源码分析,百万级系统设计,系统上线的一些坑,MQ专题,真实面试题,每天都会回答大家提出的问题,免费修改简历,免费回答工作中的问题。

星球目前开通了9个优质专栏:技术选型、系统设计、踩坑分享、工作实战、底层原理、Spring源码解读、痛点问题、高频面试题 和 性能优化。




加入星球如果不满意,3天内包退。