cpu分析利器 — async-profiler

捉虫大师 等级 1110 0 0

本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。

简介

async-profiler是一款采集分析java性能的工具,翻译一下github上的项目介绍:

async-profiler是一款没有Safepoint bias problem的低开销java采集分析器,它利用HotSpot特殊的api来收集栈信息以及内存分配信息,可以在OpenJDK,Oracle JDK以及一些其他的基于HotSpot的java虚拟机。async-profiler可以追踪以下几种事件:

  • cpu周期
  • 硬件和软件性能计数器,例如高速缓存未命中,分支未命中,页面错误,上下文切换等
  • Java堆中内存的分配
  • 锁尝试,包括Java对象监视器和ReentrantLock

使用方法

首先下载async-profiler,github主页(https://github.com/jvm-profiling-tools/async-profiler) 上有已经编译好的文件,找到对应的平台下载即可

cpu分析利器 — async-profiler

基本用法

下载好的文件解压后,有一个profiler.sh脚本,运行脚本即可对java进程进行cpu分析,例如java进程id为1232

./profiler.sh start 1232
./profiler.sh stop 1232

或者可以用-d指定剖析的时间(秒)

./profiler.sh -d 30 1232 

执行完成后会输出采集的信息:

cpu分析利器 — async-profiler

通常我们会用更加直观的火焰图来绘制输出的信息,使用参数-f {$file_name}.svg

./profiler.sh -d 30 -f ./nacos.svg 1232

命令执行完成后会生成一个svg格式的文件,用浏览器打开

cpu分析利器 — async-profiler

火焰图怎么看?可以参考阮一峰的文章

《如何读懂火焰图》 http://www.ruanyifeng.com/blog/2017/09/flame-graph.html

简单来说:x轴是抽样数,x轴越长说明被这个方法被抽样的次数越多,消耗cpu时间也越长 y轴是栈的深度,通常越往上越细,如果发现往上有一个平顶,且平顶很宽,则说明它可能有问题,消耗cpu时间较多。

其他参数介绍

  • -e event

event 可选参数用这个命令来查看

./profiler.sh list list 1232

输出样例:

cpu分析利器 — async-profiler

event 默认为cpu,也可以用alloc来查看内存分配

./profiler.sh -e alloc -d 30 -f ./nacos-alloc.svg 1232

cpu分析利器 — async-profiler

lock查看锁情况:

cpu分析利器 — async-profiler

其他的模式这里就不一一尝试,用的最多的还是cpu模式。

  • -i N 设置采样频率,默认是10ms,可使用ms,us,s作为单位,无单位默认为纳秒,如
./profiler.sh -i 500us -d 30
  • -j N 设置栈采样深度

  • -o fmt 设置输出格式:可选的有 summary、traces、flat、jfr、collapsed、svg、tree,最常用的是svg

更多命令可参考async-profiler github主页

一次网关性能压测实例

笔者有一次在压测全链路异步网关时,RPS在2000左右,始终上不去,cpu消耗比较高,于是使用async-profiler进行cpu剖析,生成的火焰图如下

cpu分析利器 — async-profiler

可以看到这里有个宽又深的栈,它消耗了很多cpu,限于图像大小,再往上拉,看下这块到底是什么

cpu分析利器 — async-profiler

从类名就能看出是log4j,猜测是代码某处打日志过于频繁导致,找到打日志的地方后先去掉日志,压测了一下,果然RPS提升到了5000,一处小小的日志竟有如此大的影响。

原理介绍

看到这里相信你应该会用async-profiler来进行cpu剖析了,如果感兴趣可以了解下async-profiler实现的原理,这块有一篇文章介绍的很详细,可以参考

《JVM CPU Profiler技术原理及源码深度解析》 https://mp.weixin.qq.com/s/RKqmy8dw7B7WtQc6Xy2CLA

简单总结一下:

  • cpu profiler实现一般有两种方案:(1)Sampling,采样(2)Instrumentation,埋点;采样对性能损耗较小但没那么准确,埋点(类似AOP)精准但性能影响大
  • Sampling采样只能在Safe Point处采样,会导致统计结果偏差,也就是开头说的Safepoint bias problem,例如某些方法执行时间短,但执行频率高,正真占用了cpu,这部分如果Sampling的采样频率不能足够小,可能就采样不到,但采样频率过高又会影响性能,这就是一般的基于采样的cpu profiler的缺点
  • async-profiler是基于采样实现的,但它又没有Safepoint bias problem,它是通过一种叫做AsyncGetCallTrace的方式来采样,这种采样不需要在安全点处采样,但这个函数不是那么容易就调用到的,需要使用一些技巧(黑科技)的方式来获取

正是第三点原因我才写了这篇文章来推荐这款cpu分析利器,比如我用了一款其他的分析器(uber-common/jvm-profiler)来分析上面网关的cpu,得出了如下的火焰图

cpu分析利器 — async-profiler

如果是这样,完全没法找到问题。而且阿里开源的Arthas中的cpu分析也是使用的async-profiler。所以你不试试吗?


搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

cpu分析利器 — async-profiler

收藏
评论区

相关推荐

操作系统
一、进程的相关概念 1.1 定义 进程用来描述一个程序及其执行过程中的信息,即描述一个执行中的程序, 所以才将其命名为进程,即进行中的程序,也可以说进程是程序的一次执行。 1.2 进程的状态 操作系统中的进程状态主要包括∶运行态—— 当前占有CPU、正在执行的进程状态;就绪态——一个进程具备了所有可以执行的条件,只要获得 CPU 就能开始执
android 面试题总结
Java部分 一、多线程   Join()  线程加入,执行此方法的线程优先使用cpu   Yeild()  线程释放资源使所有线程能有相等的机会使用cpu   Sleep() 相当于让线程睡眠,交出CPU,让CPU去执行其他的任务(不会释放锁)。 Wait()方法会让线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。
CPU负载过高异常排查实践与总结
昨天下午突然收到运维邮件报警,显示数据平台服务器cpu利用率达到了98.94%,而且最近一段时间一直持续在70%以上,看起来像是硬件资源到瓶颈需要扩容了,但仔细思考就会发现咱们的业务系统并不是一个高并发或者CPU密集型的应用,这个利用率有点太夸张,硬件瓶颈应该不会这么快就到了,一定是哪里的业务代码逻辑有问题。 1、排查思路 1.1 定位高负载进程 首先
python中的各种锁
一、全局解释器锁(GIL)   1、什么是全局解释器锁       在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使    用权消失后才能使用全局解释器(cpu),即时多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局    解释器锁(GIL)。  
巨大提升!更快的 async 函数和 promises
(https://imghelloworld.osscnbeijing.aliyuncs.com/669a1c8f7203559afa4621628303674c.png) 翻译自:Faster async functions and promises(https://v8.dev/blog/fastasync) JavaScript
Kubernetes自定义调度器 — 初窥门径
通过上一篇文章对schedulerframework调度框架已经有了大致了解,根据我们的实际生产的一些问题(如计算服务没有被调度到实际CPU最优的节点)和需求,来实现一个简单的基于CPU指标的自定义调度器。自定义调度器通过kubernetes资源指标服务metricsserver来获取各节点的当前的资源情况,并进行打分,然后把Pod调度到分数最高的节
浅谈 vue 前端同构框架 nuxt 及其性能优化
前言使用 nuxt.js 做项目也接近快一年了,从立项到内测、公测、再到正式上线,还有后面的不断维护,也陆陆续续的踩了很多坑,其中最大的问题就是 node 的渲染性能问题了。模板转换是 cpu 密集型的操作,node 又是单线程的,并发一高,cpu 就会飙到 100% 。为了提
为什么单线程的Redis能支持高并发?
一、Redis为什么是单线程注意:redis 单线程指的是网络请求模块使用了一个线程,即一个线程处理所有网络请求,其他模块仍用了多个线程。因为CPU不是Redis的瓶颈。Redis的瓶颈最有可能是机器内存或者网络带宽,既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。关于redis的性能,官方网站也有,普通笔记本轻松处理每秒几十万
商业数据分析从入门到入职(5)Python基本语法和数据类型
一、从计算机到Python 1.计算机与程序思维计算机最核心的三个部分为CPU、内存和硬盘,都在主板上面,除此之外,还包括键盘、鼠标等输入设备和屏幕等输出设备,如下:CPU用于进行计算,硬盘用于存储数据和文件,内存(包括缓存)用于连接CPU和硬盘,作为两者的缓冲,可以加快读取和处理速率。冯·诺依曼架构如下:程序是指定如何执行计
Prometheus + Grafana 快速上手
+ 快速上手,监控主机的 CPU, GPU, MEM, IO 等状态。 前提 客户端 Node Exporter用于采集 UNIX 内核主机的数据,并解压:bashwget https://github.com/prometheus/nodeexporter/releases/download/v1.1.2/nodeexporter1.1.2.linux
maven打包速度优化
mvn clean install T 1C Dmaven.test.skiptrue Dmaven.compile.forktrueT 1C :代表每个CPU核心跑一个工程。Dmaven.test.skiptrue :代表跳过测试。Dmaven.compile.forktrue :使用多线程编译注:我的项目快了十几秒jvm虚拟机优化:Xms256m Xmx
盘点golang中的开发神器
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。在Java中,我们用Junit做单元测试,用JMH做性能基准测试(benchmark),用asyncprofiler剖析cpu性能,用jstack、jmap、arthas等来排查问题。作为一名比较新的编程语言,golang的这些工具是否更加好用呢? 单元测
小白想学python,怎么做?
小白需要怎么学习python,python学习的难度大吗?学python需要从哪学起?学Python难?首先,我们普及一下编程语言的基础知识。编程语言的作用是为了让计算机干活,比如下载视频,音乐编辑文档等,而计算机干活的CPU只认识机器指令,所以,尽管编程语言不同,最后都要翻译成CPU能听懂的语言。而不同的编程语言,干同一个活,编写的代码量,差距也很大。Py
cpu分析利器 — async-profiler
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 简介asyncprofiler是一款采集分析java性能的工具,翻译一下github上的项目介绍:asyncprofiler是一款没有Safepoint bias problem的低开销java采集分析器,它利用HotSpot特殊的api来收集栈信息以及
写了一年golang,来聊聊进程、线程与协程
本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 进程在早期的单任务计算机中,用户一次只能提交一个作业,独享系统的全部资源,同时也只能干一件事情。进行计算时不能进行 IO 读写,但 CPU 与 IO 的速度存在巨大差异,一个作业在 CPU 上所花费的时间非常少,大部分时间在等待 IO。为了更合理的利用