性能分析-java程序篇之案例-工具和方法
1. 背景说明
线上服务响应时间超过40秒,登录服务器发现cpu将近100%了(如下图),针对此问题,本文说明排查过程、工具以定位具体的原因。

# 2. 分析排查过程
此类问题的排查,有两款神器可用,分别是async-profiler和arthas,async-profiler主要用于全局分析,通过此工具可以找到热点方法,
再用arthas对此热点方法进行详细的追踪,trace命令可以追踪方法的具体耗时,watch命令可以查看方法的出入参数,在结合源代码可以比较
方便定位到问题原因。下面记录排查过程:
## 2.1. 用async-profiler生成火焰图
到下载后,解压后如下所示:

执行命令生成火焰图:
./profiler.sh -d 300 1485 -f ./test.svg
其中 -d 300 表示采集300s的数据,300s结束后,自动生成test.svg文件到当前目录。
2.2. 火焰图分析
用浏览器打开上面生成的svg文件,如下:

火焰图中纵向代表调用栈,即方法的调用深度,横向是方法占用cpu的时间比率,因此火焰图中如果出现平顶现象,说明相关方法耗时长(即为热点方法),是分析优化的对象;
从上图可看出:java/util/ComparableTimSort.countRunAndMakeAscending方法为热点方法,可以根据此方法的调用栈对相关方法进行追踪:
io/micrometer/core/instrument/MeterRegistry.getMappedId
io/micrometer/core/instrument/Tags.and
2.3. 追踪方法具体耗时和调用关系
此时可采用arthas工具,改工具的安装和使用方法可参考:《arthas用户指南》
2.3.1. 追踪getMappedId
arthas控制台中执行下面命令:
trace io.micromete/core.instrument.MeterRegistry getMappedId

io.micrometer.core.instrument.MeterRegistry#getMappedId耗时近40s,期间此方法中调用了2458次MeterFilter.map()方法: 该方法源代码如下:

通过多次执行该命令发现,filters数组会随着请求增加而不断上涨;那么这个filters数组到底是什么内容呢?
2.3.2. 监控类的返回对象
watch *MeterRegistry * "{returnObj}" -x 3 -n 3

发现数组中储存的都是相同内容的tag,继续查看源代码,io.micrometer.core.instrument.MeterRegistry类中成员变量赋值的相关代码:

2.3.3. 监控Tags and方法的入参
watch io.micrometer.core.instrument.Tags and "{params}" -x 2 -b -n 4

2.4. 原因
commonTags每调用一次,filters数组长度+1,会进行一次copy,不断增长,getMappedId方法中循环对tag进行and操作、排序、去重导致cpu飙高;
下面是导致这个问题原因精简后的模拟代码:

2.5. 解决方式
commonTags应在服务初始化的时候设置,如在spring boot的配置文件中设置:

性能分析-java程序篇之案例-工具和方法的更多相关文章
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 原文链接 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能 ...
- 【转】一文掌握 Linux 性能分析之网络篇
[转]一文掌握 Linux 性能分析之网络篇 比较宽泛地讲,网络方向的性能分析既包括主机测的网络配置查看.监控,又包括网络链路上的包转发时延.吞吐量.带宽等指标分析.包括但不限于以下分析工具: pin ...
- 【转】一文掌握 Linux 性能分析之内存篇
[转]一文掌握 Linux 性能分析之内存篇 前面我们已经学习了 CPU 篇,这篇来看下内存篇. 01 内存信息 同样在分析内存之前,我们得知到怎么查看系统内存信息,有以下几种方法. 1.1 /pro ...
- 一文掌握 Linux 性能分析之网络篇
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 这是 Linu ...
- 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01
百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...
- 【转】一文掌握 Linux 性能分析之网络篇(续)
[转]一文掌握 Linux 性能分析之网络篇(续) 在上篇网络篇中,我们已经介绍了几个 Linux 网络方向的性能分析工具,本文再补充几个.总结下来,余下的工具包括但不限于以下几个: sar:统计信息 ...
- 【转】一文掌握 Linux 性能分析之 CPU 篇
[转]一文掌握 Linux 性能分析之 CPU 篇 平常工作会涉及到一些 Linux 性能分析的问题,因此决定总结一下常用的一些性能分析手段,仅供参考. 说到性能分析,基本上就是 CPU.内存.磁盘 ...
- 一文掌握 Linux 性能分析之网络篇(续)
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 这是 Linu ...
- 如何利用JConsole观察分析Java程序的运行并进行排错调优_java
如何利用JConsole观察分析Java程序的运行并进行排错调优_java 官方指导 use jconsole use jmx technology
随机推荐
- 【ZooKeeper系列】2.用Java实现ZooKeeper API的调用
温馨提示:在这里我再次提个小要求,希望大家能习惯看官方文档,文档虽然是英文但用词都比较简单,基本都能看懂文档表达的意思.授之以鱼不如授之以渔的道理相信大家都明白,也希望通过猿人谷的这个ZooKeepe ...
- Java读取Properties文件 Java加载配置Properties文件
static{ Properties prop = new Properties(); prop.load(Thread.currentThread().getContextClassLoader() ...
- python学习-if
# 判断"""if 条件(True/False): 条件为真时,执行的代码(要干的事情)[elif 条件: 条件为真时,执行的代码(要干的事情)elif 条件: 条件为真 ...
- java基础篇二
引言 滴,第二天卡. 五.关键字 -static -初始化顺序 -静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代 ...
- JS基础语法---函数作为返回值使用
结论:函数是可以作为返回值使用的 function f1() { console.log("f1函数调用了"); return function() { console.log(& ...
- centos_mysql 安装脚本
#!/bin/bash env echo "Download msyql5.7 rpm..." sudo yum install wget wget -i -c http://de ...
- docker容器和虚拟机的比较
containers:容器是在应用层的抽象化,多个容器能够运行在同一台机器上,和其他容器共享操作系统的核,每个容器运行都独立的运行在用户的空间内.容器需要的空间比虚拟机要小(容器镜像的大小一般为MBs ...
- 使用 Redis 进行阅读数统计并定时持久化
之前,统计每篇博文的阅读数的方式是经过筛选去重之后直接更新数据库,并发压力直接传导到数据库,假设1秒有1000个并发请求,传统方案会在1秒内并发进行1000次数据库更新操作. 为了降低数据库的并发压力 ...
- Git 原理简谈
Git 本身是一个对 reference 进行管理的数据库,reference 指的是对原始数据的引用.通过对原始数据的追踪,那么就可以做到对版本的控制.Git 使用一个 DAG 存储了整个的refe ...
- webpack 打包less文件配置
1 npm install less less-loader -D 2匹配规则