性能分析工具-持续更新

1 arthas

1.1. arthas查询方法执行时间

arthas是一款由阿里巴巴开发的Java诊断利器,可以用它来定位不少问题。

官网:https://arthas.aliyun.com/doc/arthas-tutorials?language=cn

1.1.1. arthas原理

  1. 通过jdk提供的Instrument和Attach API接口,入口为agentmain函数,arthas能够对JVM底层组件进行访问,可参考:https://blog.csdn.net/u010862794/article/details/87773434
  2. 通过ASM,一种Java字节码操作框架,arthas实现了Enhancer和AdviceWeaver方法,用来动态生成class或增强class

1.1.2. arthas应用场景

例如说,将arthas.jar放在服务端上,启动它之后,可以查看:

  1. 出现不可预知的bug后,无法在本地复现。无法debug,arthas可以用它来查看正在执行的服务端的具体数据:反编译正在执行的代码,查看入参与出参,定位代码执行的情况。
  2. 性能优化,查看方法的调用路径,并输出每个节点的执行时间。
  3. 监控线上JVM的实时运行状态(Thread、GC、Memory、Runtime、堆栈的情况)
  4. 查看CPU使用率TopN的线程、排查阻塞的线程

1.1.3. arthas查看执行方法的情况

通过arthas,可以查看执行方法链的情况,找到耗时最长的方法:demo.MathGame

$ trace --skipJDKMethod false demo.MathGame run
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 60 ms.
`---ts=2019-12-04 00:44:41;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[1.357742ms] demo.MathGame:run()
        +---[0.028624ms] java.util.Random:nextInt() #23
        +---[0.045534ms] demo.MathGame:primeFactors() #24 [throws Exception]
        +---[0.005372ms] java.lang.StringBuilder:<init>() #28
        +---[0.012257ms] java.lang.Integer:valueOf() #28
        +---[0.234537ms] java.lang.String:format() #28
        +---[min=0.004539ms,max=0.005778ms,total=0.010317ms,count=2] java.lang.StringBuilder:append() #28
        +---[0.013777ms] java.lang.Exception:getMessage() #28
        +---[0.004935ms] java.lang.StringBuilder:toString() #28
        `---[0.06941ms] java.io.PrintStream:println() #28
 
`---ts=2019-12-04 00:44:42;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[3.030432ms] demo.MathGame:run()
        +---[0.010473ms] java.util.Random:nextInt() #23
        +---[0.023715ms] demo.MathGame:primeFactors() #24 [throws Exception]
        +---[0.005198ms] java.lang.StringBuilder:<init>() #28
        +---[0.006405ms] java.lang.Integer:valueOf() #28
        +---[0.178583ms] java.lang.String:format() #28
        +---[min=0.011636ms,max=0.838077ms,total=0.849713ms,count=2] java.lang.StringBuilder:append() #28
        +---[0.008747ms] java.lang.Exception:getMessage() #28
        +---[0.019768ms] java.lang.StringBuilder:toString() #28
        `---[0.076457ms] java.io.PrintStream:println() #28

2. es的profile

可以执行es的profile api,查看执行es的查询语句时,什么节点比较耗时,用于分析,优化es查询效率

2.1. 参考文档

文档入口:https://docs.kilvn.com/elasticsearch/docs/132.html

2.2. 启用方法

ES常见的慢查询优化方案是使用es本身的 profile API,举例如下:

GET /_search
{
  "profile": true,
  "query" : {
    "match" : { "message" : "message number" }
  }
}

2.3. 整体结构

其中返回的数据结构如下:

"profile": {
        "shards": [
           {
              "id": "[hWxBcjaPSpqccQtJmN][user_tag][1]",  
              "searches": [
                 {
                    "query": [...],             
                    "rewrite_time": 7861,      
                    "collector": [...]          
                 }
              ],
              "aggregations": [...]             
           }
        ]
}

searches:有三个元素,每个元素都有各自的属性与含义:

  1. query:分析分块执行生成的查询树的详细时序

  2. rewrite_time:查询重写一个或多个组合查询的时间

  3. collector:负责协调匹配文档的遍历、得分和集合

aggregations:包含了聚合过程中具体执行信息。

2.3.1 query

  1. type:查询类型,常见的有BooleanQuery,TermQuery等

  2. time/time_in_nanos:执行该查询所用的时间,包括children的时间

  3. breakdown:主要与lucene参数有关,记录Lucene的运转实际上耗费时间的

  4. children:具有多个关键字的查询被拆成相应术语的布尔查询

"query": [
    {
       "type": "BooleanQuery",
       "description": "message:message message:number",
       "time": "1.873811000ms",
       "time_in_nanos": "1873811",
       "breakdown": {...},               
       "children": [
          {
             "type": "TermQuery",
             "description": "message:message",
             "time": "0.3919430000ms",
             "time_in_nanos": "391943",
             "breakdown": {...}
          },
          {
             "type": "TermQuery",
             "description": "message:number",
             "time": "0.2106820000ms",
             "time_in_nanos": "210682",
             "breakdown": {...}
          }
       ]
    }
]

"breakdown": {
   "score": 51306,
   "score_count": 4,
   "build_scorer": 2935582,
   "build_scorer_count": 1,
   "match": 0,
   "match_count": 0,
   "create_weight": 919297,
   "create_weight_count": 1,
   "next_doc": 53876,
   "next_doc_count": 5,
   "advance": 0,
   "advance_count": 0
}

2.3.2. rewrite_time

"rewrite_time": 12345

2.3.3. collector

  1. name:收集器名称

  2. reason:详细

  3. time_in_nanos:收集执行花费的时间

  4. children:收集器(Collector)由SimpleTopScoreDocCollector包装成 CancellableCollector

"collector": [
   {
      "name": "CancellableCollector",
      "reason": "search_cancelled",
      "time": "0.3043110000ms",
      "time_in_nanos": "304311",
      "children": [
        {
          "name": "SimpleTopScoreDocCollector",
          "reason": "search_top_hits",
          "time": "0.03227300000ms",
          "time_in_nanos": "32273"
        }
      ]
   }
]

SimpleTopScoreDocCollector是Elasticsearch使用的默认的“评分和排序”的收集器(Collector)

3 junitperf

3.1. junitperf特点

  1. 适配支持 Junit4、Junit5,入门简单

  2. 能够提供简单的性能报告支持自定义拓展

3.2. junitperf使用方式

3.2.1. 引入方式

<!--junit的基础上,可用于junit4-->
<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>junitperf</artifactId>
    <version>1.0.3</version>
</dependency>
<!--junit的基础上,可用于junit5-->
 <dependency>
     <groupId>com.github.houbb</groupId>
     <artifactId>junitperf</artifactId>
     <version>2.0.7/version>
     <scope>test</scope>
</dependency>

3.2.2. 代码最简单使用

import com.github.houbb.junitperf.core.annotation.JunitPerfConfig;
import com.github.houbb.junitperf.core.rule.JunitPerfRule;
import com.Application;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @Autor lietobrain
 * @Date 2022/5/17 13:19
 * @Desc: JunitPerf使用
 */
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
    @Rule
    public JunitPerfRule junitPerfRule = new JunitPerfRule();

    /**
    *  duration:执行时间(不包含准备时间)300000ms,5min
    *  threads :100个线程用户
    *  warmUp:准备时间(单位:毫秒)
    */
    @Test
    @JunitPerfConfig(duration = 300000, threads = 100, warmUp = 20)
    public void testESCount() {
          // ... 测试代码:service.xxxx();
    }
}

3.2.3. 坑

  1. @Before这些前置或者后置方法,在JunitPerf下都会反复执行,并不是说100个线程同时跑,而会每次都调用@Before,这块要注意
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容