性能分析-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
 
随机推荐
- sendRedirect()和forward()方法有什么区别?
			
forward是服务器内部的跳转,浏览器的地址栏不会发生变化,同时可以把request和response传递给后一个请求.sendRedirect()是浏览器方面的跳转,要发送两次请求,地址栏也会发生 ...
 - 表删除时 Cannot delete or update a parent row: a foreign key constraint fails 异常处理
			
有两张表,结构如下: t_item: t_bid: id int id int n ...
 - 《Java知识应用》Java加密方式(MD5)详解
			
1. 应用 使用MD5加密 因为:因为MD5的不可逆性,也可以保证你的key 是安全的,黑客无法通过原文和密文知晓你的key. 案例: import java.math.BigInteger; imp ...
 - JavaScript图形实例:五角星
			
1.五角星 在半径为80的圆周上取5个点,用这5个点依次首尾连接画5条线,可以绘制出一个五角星图案. 编写如下的HTML代码. <!DOCTYPE html> <head> & ...
 - Mysql数据库的主从与主主
			
前言: 首先,我们得知道我们为什么要做数据库的主从与主主,而后,再讨论他们的优劣与特点:为什么要做主从呢?因为Mysql数据库没有增量备份的机制,当数据量太大的时候备份是个难以解决的问题.但是mysq ...
 - 脚本批量执行Redis命令
			
1.将命令写在文件中 数据量比较大的话,建议用程序去生成文件.例如: List<String> planIdList = planDao.findAll().parallelStream( ...
 - 微服务与敏捷开发(Scrum/Kanban)的核心思想之我见
			
微服务与敏捷开发(Scrum/Kanban)的核心思想之我见 关于"微服务"和"敏捷开发"的文章网络上有很多,所以这里不再重复叙述这些概念的解释和特点,而是 ...
 - kafka2.3.1+zookeeper3.5.6+kafka-manager2.0.0.2集群部署(centos7.7)
			
一.准备三台服务器,配置好主机名和ip地址 二.服务器初始化:包括安装常用命令工具,修改系统时区,校对系统时间,关闭selinux,关闭firewalld,修改主机名,修改系统文件描述符,优化内核参数 ...
 - ESLint + Prettier + husky + lint-staged 规范统一前端代码风格
			
写在前面: ESLint: Find and fix problems in your JavaScript code. Prettier: Prettier is an opinionated co ...
 - 面试连环炮系列(五):你们的项目为什么要用RabbitMQ
			
你们的项目为什么要用RabbitMQ? 消息队列的作用是系统解耦.同步改异步.请求消峰,举个下订单的例子: 前端获取用户订单信息,请求后端的订单创建接口.这个接口并不直接请求订单服务,而是首先生成唯一 ...