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程序篇之案例-工具和方法的更多相关文章

  1. 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行

    利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 原文链接 一.JConsole是什么 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能 ...

  2. 【转】一文掌握 Linux 性能分析之网络篇

    [转]一文掌握 Linux 性能分析之网络篇 比较宽泛地讲,网络方向的性能分析既包括主机测的网络配置查看.监控,又包括网络链路上的包转发时延.吞吐量.带宽等指标分析.包括但不限于以下分析工具: pin ...

  3. 【转】一文掌握 Linux 性能分析之内存篇

    [转]一文掌握 Linux 性能分析之内存篇 前面我们已经学习了 CPU 篇,这篇来看下内存篇. 01 内存信息 同样在分析内存之前,我们得知到怎么查看系统内存信息,有以下几种方法. 1.1 /pro ...

  4. 一文掌握 Linux 性能分析之网络篇

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 这是 Linu ...

  5. 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01

    百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  6. 【转】一文掌握 Linux 性能分析之网络篇(续)

    [转]一文掌握 Linux 性能分析之网络篇(续) 在上篇网络篇中,我们已经介绍了几个 Linux 网络方向的性能分析工具,本文再补充几个.总结下来,余下的工具包括但不限于以下几个: sar:统计信息 ...

  7. 【转】一文掌握 Linux 性能分析之 CPU 篇

    [转]一文掌握 Linux 性能分析之 CPU 篇 平常工作会涉及到一些 Linux 性能分析的问题,因此决定总结一下常用的一些性能分析手段,仅供参考. 说到性能分析,基本上就是 CPU.内存.磁盘 ...

  8. 一文掌握 Linux 性能分析之网络篇(续)

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 这是 Linu ...

  9. 如何利用JConsole观察分析Java程序的运行并进行排错调优_java

    如何利用JConsole观察分析Java程序的运行并进行排错调优_java 官方指导  use jconsole use jmx technology

随机推荐

  1. win10 修改用户目录为英文

    win10家庭版怎样进入 administratornet user administrator /active:yes net user administrator /active:no

  2. 判断浏览器是否启用cookie

    <!DOCTYPE html> <html> <body onload="checkCookies()"> <script> fun ...

  3. tinymce插件preview改造增加全屏按钮

    近期需要用到tinymce的preview插件,但preview出来的界面太小了,通过投影仪出来看的不清晰,于是想在preview的预览界面中增加全屏.放大和缩小的按钮,改造内容如下: 由于previ ...

  4. DS-5获取License

    1.点击Eclipse for DS-5,打开DS-5,弹出workspace选择窗口   2.点击OK,打开DS-5,弹出License窗口,license需要自己去解决

  5. 线程中put(None)和主函数中put(None)的区别和用法

    ''' 初试生产者消费者模型代码 分析: 对象含有生产者.队列.消费者 Queue队列模块,不适合传大文件,通常传一些消息. ''' '''多生产者进程和多消费者进程''' #导入模块 from mu ...

  6. 数组知识总结(js)

    js数组知识注意点: 声明空数组时,和c语言中的不同 js c var arr=[ ] //合法,声明一个空数组,数组长度为0; int a[];//错误因为在c中声明一个数组不仅要指定类型还要指定数 ...

  7. Android 表格布局 TableLayout

    属性介绍 stretchColumns:列被拉伸 shrinkColumns:列被收缩 collapseColumns:列被隐藏 举例测试 <TableLayout android:id=&qu ...

  8. Cookie与Session会话技术

    Cookie与Session会话技术 一.什么是会话 会话:当用户打开浏览器,访问多个WEB资源,然后关闭浏览器的过程,称之为一个会话,选项卡,弹出页面都属于这个会话,且共享同一个session. 二 ...

  9. Java连载60-类之间的六种关系

    一.类之间的关系 1.泛化关系(UML图:实线空心三角形箭头,箭头指向被继承方) 类和类.接口与接口之间的继承称为泛化关系 public class A {} class B extends A{} ...

  10. 文件系统之parted 分区

    parted分区命令 1.分区表区别 我们 Linux 系统中有两种常见的分区表 MBR 分区表(主引导记录分区表)和 GPT 分区表(GUID 分 区表) MBR 分区表:支持的最大分区是 2TB( ...