在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

測試和性能監控神器JMH和Arthas

jf_ro2CN3Fa ? 來源:芋道源碼 ? 作者:芋道源碼 ? 2022-11-09 17:19 ? 次閱讀

最近的工作日并不算太平,各種大大小小的case和解case,發現已經有好久好久沒有靜下心來專心寫點東西了。不過倒還是堅持利用業余時間學習了不少微課上的東西,發現大佬們總結的東西還是不一樣,相比于大學時的那些枯燥的課本,大佬們總結出來的內容更活,更加容易理解。自己后面也會把大佬們的東西好好消化吸收,變成自己的東西用文字性的東西表達出來。

今天想總結的東西是最近工作中使用到的測試工具JMH以及Java運行時監控工具Arthas。他們在我的實際工作中也算是幫了大忙。所以在這里拋磚引玉一下這些工具的使用方法。同時也加深一下自己對這些工具的熟悉程度。對這兩個工具,我都會首先簡單介紹一下這些工具的大致使用場景,然后會使用一個在工作中真正遇到的性能問題排查為例詳細講解這兩個工具的實際用法。話不多說,直奔主題。

問題描述

為了能夠讓我后面的實例能夠貫穿這兩個工具的使用,我首先簡單描述下我們在開發中遇到的實際的性能問題。然后再引出這兩個性能工具的實際使用,看我們如何使用這兩個工具成功定位到性能瓶頸的。

問題如下:為了能夠支持丟失率,我們將原先log4j2 的Async+自定義Appender的方式進行了修正,把異步的邏輯放到了自己改版后的Appender中。但我們發現修改后日志性能要比之前Async+自定義Appender的方式下降不少。這里由于隱私原因我并沒有用實際公司中的實例,這里我用了一種其他同樣能夠體現問題的方式。我們暫時先不給出具體的配置文件,先給出性能測試代碼和結果

代碼

packagecom.bryantchang.appendertest;

importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;

publicclassAppenderTest{

privatestaticfinalStringLOGGER_NAME_DEFAULT="defaultLogger";
privatestaticfinalStringLOGGER_NAME_INCLUDE="includeLocationLogger";
privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(LOGGER_NAME_INCLUDE);
publicstaticfinallongBATCH=10000;

publicstaticvoidmain(String[]args)throwsInterruptedException{
while(true){
longstart,end;
start=System.currentTimeMillis();
for(inti=0;i

代碼邏輯及其簡單,就是調用logger.info每次打印10000條日志,然后記錄耗時。兩者的對比如下

117551d0-5cb1-11ed-a3b6-dac502259ad0.png

從這兩張圖片中我們能夠看到同樣的邏輯,兩個程序的耗時差距相差了數十倍,但看圖片,貌似僅僅是logger的名稱不一樣。對上面的實驗結果進行分析,我們可能會有兩個疑問

上面的代碼測試是否標準,規范

如果真的是性能問題,那么這兩個代碼到底在哪個方法上有了這么大的差距導致了最終的性能差異

下面這兩個工具就分別來回答這兩個問題

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

JMH簡介

第一個問題就是,測試的方法是否標準。我們在編寫代碼時用的是死循環+前后“掐秒表”的方式。假如我們要再加個多線程的測試,我們還需要搞一個線程池,除了代碼本身的邏輯還要關心測試的邏輯。我們會想,有沒有一款工具能夠將我們從測試邏輯中徹底解放出來,只需要關心我們需要測試的代碼邏輯。JMH就是這樣一款Java的測試框架。下面是JMH的官方定義

JMH是一個面向Java語言或者其他Java虛擬機語言的性能基準測試框架

這里面我們需要注意的是,JMH所測試的方法約簡單越好,依賴越少越好,最適合的場景就是,測試兩個集合put,get性能,例如ArrayList與LinkedList的對比等,這里我們需要測試的是批量打一批日志所需要的時間,也基本符合使用JMH的測試場景。下面是測試代碼,bench框架代碼以及主函數。

待測試方法

publicclassLogBenchMarkWorker{

privateLogBenchMarkWorker(){}

privatestaticclassLogBenchMarkWorkerInstance{
privatestaticfinalLogBenchMarkWorkerinstance=newLogBenchMarkWorker();
}

publicstaticLogBenchMarkWorkergetInstance(){
returnLogBenchMarkWorkerInstance.instance;
}

privatestaticfinalStringLOGGER_DEFAULT_NAME="defaultLogger";
privatestaticfinalStringLOGGER_INCLUDE_LOCATION="includeLocationLogger";
privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(LOGGER_DEFAULT_NAME);
privatestaticlongBATCH_SIZE=10000;

publicvoidlogBatch(){
for(inti=0;i

可以看到待測試方法非常簡單,就是單批次一次性打印10000條日志的操作,所以并沒有需要額外說明的部分。下面我們再來看benchmark部分。

publicclassLogBenchMarkMain{

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Fork(value=1)
@Threads(1)
publicvoidtestLog1(){
LogBenchMarkWorker.getInstance().logBatch();
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Fork(value=1)
@Threads(4)
publicvoidtestLog4(){
LogBenchMarkWorker.getInstance().logBatch();
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Fork(value=1)
@Threads(8)
publicvoidtestLog8(){
LogBenchMarkWorker.getInstance().logBatch();
}

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@Fork(value=1)
@Threads(16)
publicvoidtestLog16(){
LogBenchMarkWorker.getInstance().logBatch();
}

在這段代碼中,我們就會發現有了一些JMH中特有的東西,我下面進行簡要介紹。

Benchmark注解:標識在某個具體方法上,表示這個方法將是一個被測試的最小方法,在JMH中成為一個OPS
BenmarkMode:測試類型,JMH提供了幾種不同的Mode
    Throughput:整體吞吐量
    AverageTime:調用的平均時間,每次OPS執行的時間
    SampleTime:取樣,給出不同比例的ops時間,例如99%的ops時間,99.99%的ops時間
fork:fork的次數,如果設置為2,JMH會fork出兩個進程來測試
Threads:很容易理解,這個參數表示這個方法同時被多少個線程執行

在上面的代碼中,我定義了4個待測試的方法,方法的Fork,BenchmarkMode均為測試單次OPS的平均時間,但4個方法的線程數不同。除了這幾個參數,還有幾個參數,我會在main函數里面來講,main代碼如下所示

publicclassMain{
publicstaticvoidmain(String[]args)throwsRunnerException{
Optionsoptions=newOptionsBuilder()
.include(LogBenchMarkMain.class.getSimpleName())
.warmupIterations(5)
.measurementIterations(5)
.output("logs/BenchmarkCommon.log")
.build();
newRunner(options).run();
}
}

我們可以看到,在main函數中,我們就是要設置JMH的基礎配置,這里面的幾個配置參數含義如下:

include:benchmark所在類的名字,可以使用正則表達
warmupIteration:預熱的迭代次數,這里為什么要預熱的原因是由于JIT的存在,隨著代碼的運行,會動態對代碼的運行進行優化。因此在測試過程中需要先預熱幾輪,讓代碼運行穩定后再實際進行測試
measurementIterations:實際測試輪次
output:測試報告輸出位置

我分別用兩種logger運行一下測試,查看性能測試報告對比

使用普通logger

LogBenchMarkMain.testLog1avgt50.006±0.001s/op
LogBenchMarkMain.testLog16avgt50.062±0.026s/op
LogBenchMarkMain.testLog4avgt50.006±0.002s/op
LogBenchMarkMain.testLog8avgt50.040±0.004s/op

使用了INCLUDE_LOCATION的logger

LogBenchMarkMain.testLog1avgt50.379±0.007s/op
LogBenchMarkMain.testLog16avgt51.784±0.670s/op
LogBenchMarkMain.testLog4avgt50.378±0.003s/op
LogBenchMarkMain.testLog8avgt50.776±0.070s/op

這里我們看到,性能差距立現。使用INCLUDE_LOCATION的性能要明顯低于使用普通logger的性能。這是我們一定很好奇,并且問一句“到底慢在哪”!!

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://gitee.com/zhijiantianya/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

Arthas 我的代碼在運行時到底做了什么

Arthas是阿里開源的一款java調試神器,與greys類似,不過有著比greys更加強大的功能,例如,可以直接繪制java方法調用的火焰圖等。這兩個工具的原理都是使用了Java強大的字節碼技術。畢竟我也不是JVM大佬,所以具體的實現細節沒法展開,我們要做的就是站在巨人的肩膀上,接受并用熟練的使用好這些好用的性能監控工具。

實際操作

talk is cheap, show me your code,既然是工具,我們直接進行實際操作。我們在本機運行我們一開始的程序,然后講解arthas的使用方法。

我們首先通過jps找到程序的進程號,然后直接通過arthas給到的as.sh對我們運行的程序進行字節碼增強,然后啟動arthas,命令如下

./as.shpid
119b0164-5cb1-11ed-a3b6-dac502259ad0.png

可以看到,arthas支持查看當前jvm的狀態,查看當前的線程狀態,監控某些方法的調用時間,trace,profile生成火焰圖等,功能一應俱全 我們這里也只將幾個比較常用的命令,其他的命令如果大家感興趣可以詳見官網arthas官網。這篇文章主要介紹下面幾個功能

反編譯代碼

監控某個方法的調用

查看某個方法的調用和返回值

trace某個方法

監控方法調用

這個主要的命令為monitor,根據官網的介紹,常用的使用方法為

monitor-cdurationclassNamemethodName

其中duration代表每隔幾秒展示一次統計結果,即單次的統計周期,className就是類的全限定名,methodname就是方法的名字,這里面我們查看的方法是Logger類的info方法,我們分別對使用兩種不同logger的info方法。這里面的類是org.slf4j.Logger,方法時info,我們的監控語句為

monitor-c5org.slf4j.Loggerinfo

監控結果如下

使用普通appender

11b7c88a-5cb1-11ed-a3b6-dac502259ad0.png

我們可以看到,使用include appeder的打印日志方法要比普通的appender高出了3倍,這就不禁讓我們有了疑問,究竟這兩個方法各個步驟耗時如何呢。下面我們就介紹第二條命令,trace方法。

trace命令 & jad命令

這兩個程序的log4j2配置文件如下


 

 

 

 

 












 
 




 





 














 

 








 






我們都是用了一個AsyncAppender套用了一個FileAppender。查看fileAppender,發現二者相同完全沒區別,只有asyncAppender中的一個選項有區別,這就是includeLocation,一個是false,另一個是true。至于這個參數的含義,我們暫時不討論,我們現在知道問題可能出在AsyncAppender里面,但是我們該如何驗證呢。trace命令就有了大用場。

trace命令的基本用法與monitor類似,其中主要的一個參數是-n則是代表trace多少次的意思

trace-ntrace_timesclassNamemethodName

我在之前Log4j2的相關博客里面講到過,任何一個appender,最核心的方法就是他的append方法。所以我們分別trace兩個程序的append方法。

trace-n5org.apache.logging.log4j.core.appender.AsyncAppenderappend

trace結果如下

使用普通appender

11f36f48-5cb1-11ed-a3b6-dac502259ad0.png

我們立刻可以發現,兩個trace的熱點方法不一樣,在使用include的appender中,耗時最長的方法時org.apache.logging.log4j.core.impl.Log4jLogEvent類中的createMemento方法,那么怎么才能知道這個方法到底做了啥呢,那就請出我們下一個常用命令jad,這個命令能夠反編譯出對應方法的代碼。這里我們jad一下上面說的那個createMemento方法,命令很簡單

jadorg.apache.logging.log4j.core.impl.Log4jLogEventcreateMemento

結果如下

12397cae-5cb1-11ed-a3b6-dac502259ad0.png

watch命令

watch命令能夠觀察到某個特定方法的入參,返回值等信息,我們使用這個命令查看一下這個createMemento方法的入參,如果兩個程序的入參不同,那基本可以斷定是這個原因引起命令如下

watchorg.apache.logging.log4j.core.impl.Log4jLogEventcreateMemento"params"-x2-n5-b-f

這里面的參數含義如下

-x參數展開層次
-n執行次數
-b查看方法調用前狀態
-f方法調用后

其中的param代表查看方法的調用參數列表,還有其他的監控項詳見官網官網

最終watch結果如下

使用普通logger

12540a60-5cb1-11ed-a3b6-dac502259ad0.png

果不其然,這兩個參數果然是一個true一個false,我們簡單看下這個參數是如何傳進來的,我們jad一下AsyncAppender的append方法。

12893262-5cb1-11ed-a3b6-dac502259ad0.png

不過為了一探究竟,我還是靜態跟了一下這段代碼

這個includeLocation會在event的createMemento中被用到,在序列化生成對象時會創建一個LogEventProxy,代碼如下

publicLogEventProxy(finalLogEventevent,finalbooleanincludeLocation){
this.loggerFQCN=event.getLoggerFqcn();
this.marker=event.getMarker();
this.level=event.getLevel();
this.loggerName=event.getLoggerName();

finalMessagemsg=event.getMessage();
this.message=msginstanceofReusableMessage
?memento((ReusableMessage)msg)
:msg;
this.timeMillis=event.getTimeMillis();
this.thrown=event.getThrown();
this.thrownProxy=event.getThrownProxy();
this.contextData=memento(event.getContextData());
this.contextStack=event.getContextStack();
this.source=includeLocation?event.getSource():null;
this.threadId=event.getThreadId();
this.threadName=event.getThreadName();
this.threadPriority=event.getThreadPriority();
this.isLocationRequired=includeLocation;
this.isEndOfBatch=event.isEndOfBatch();
this.nanoTime=event.getNanoTime();
}

如果includeLocation為true,那么就會調用getSource函數,跟進去查看,代碼如下

publicStackTraceElementgetSource(){
if(source!=null){
returnsource;
}
if(loggerFqcn==null||!includeLocation){
returnnull;
}
source=Log4jLogEvent.calcLocation(loggerFqcn);
returnsource;
}
publicstaticStackTraceElementcalcLocation(finalStringfqcnOfLogger){
if(fqcnOfLogger==null){
returnnull;
}
//LOG4J2-1029newThrowable().getStackTraceisfasterthanThread.currentThread().getStackTrace().
finalStackTraceElement[]stackTrace=newThrowable().getStackTrace();
StackTraceElementlast=null;
for(inti=stackTrace.length-1;i>0;i--){
finalStringclassName=stackTrace[i].getClassName();
if(fqcnOfLogger.equals(className)){
returnlast;
}
last=stackTrace[i];
}
returnnull;
}

我們看到他會從整個的調用棧中去尋找調用這個方法的代碼行,其性能可想而知。我們用arthas監控一下,驗證一下。

首先我們trace crateMemento方法

trace-n5org.apache.logging.log4j.core.impl.Log4jLogEventcreateMemento
12ad86b2-5cb1-11ed-a3b6-dac502259ad0.png
trace-n5org.apache.logging.log4j.core.impl.Log4jLogEventserialize
12e6ff78-5cb1-11ed-a3b6-dac502259ad0.png
trace-n5org.apache.logging.log4j.core.impl.Log4jLogEvent$LogEventProxy
130ec940-5cb1-11ed-a3b6-dac502259ad0.png
trace-n5trace-n5org.apache.logging.log4j.core.LogEventgetSource
135258ae-5cb1-11ed-a3b6-dac502259ad0.png

至此我們通過結合JMH和arthas共同定位出了一個線上的性能問題。不過我介紹的只是冰山一角,更多常用的命令還希望大家通過官網自己了解和實踐,有了幾次親身實踐之后,這個工具也就玩熟了。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 監控
    +關注

    關注

    6

    文章

    2234

    瀏覽量

    55365
  • 代碼
    +關注

    關注

    30

    文章

    4827

    瀏覽量

    69053
  • Case
    +關注

    關注

    0

    文章

    27

    瀏覽量

    13402

原文標題:測試和性能監控神器 JMH & Arthas

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    無線網絡智能攝像機 店鋪安防監控必備神器

    最不省心的問題有兩個:一是就是夜里的防盜問題,二是店里的員工有沒有消極怠工、偷懶打游戲,甚至有沒有挪用收銀臺的錢。下面給大家分享Vimtag智能攝像機店鋪監控必備神器。  說到店鋪安裝智能攝像機,有以下
    發表于 06-07 15:25

    使用測試工具iPerf監控無線網絡性能(轉)

    使用測試工具iPerf監控無線網絡性能(轉)
    發表于 08-17 12:37

    數十萬應用結點全息監控,ARMS新上線的應用監控神器到底有多牛?

    的應用的高效運行。而ARMS的“應用監控”就是保障這些復雜應用有效運行的秘密武器。近日,阿里中間件(Aliware)將該功能正式對外開放,目的是為用戶在應用性能管理方面提供更多便利。在微服務時代,IT企業
    發表于 12-25 13:55

    linux服務器性能測試步驟

    linux服務器性能測試-服務器實時【磁盤】監控
    發表于 06-02 06:54

    移動APP測試的android性能測試

    當應用實現了新功能后,準備發布版本前,必須進行性能測試以確定沒有性能問題,內存使用情況便是其中必須要測試性能之一。由于內存組成的復雜性,并
    發表于 06-09 16:17

    NXP電力變換的神器

    其實很早之前在公眾號給大家推送過NXP的這個神器,freeMaster,這個工具其實已經好多年了,在最早的飛思卡爾早期就存在,一直是工程師調試電機,電力變換的神器,確實好...
    發表于 09-17 06:48

    CoreSight性能監控單元架構

    體系結構包括當計數器達到閾值時產生中斷的機制。 在CoreSight性能監視單元體系結構中,事件計數器是單調增加的。但是,在某些情況下,PMU提供監控器來測量組成部分例如,監控器可能在分配資源時遞增
    發表于 08-09 07:20

    Arthas可以解決哪些問題

    診斷利器 Arthas,是阿里的一款開源工具。Github-alibaba/arthas 上可以看到它的介紹
    的頭像 發表于 12-24 14:22 ?810次閱讀

    國產測試工具神器ATECLOUD智能云測試平臺技術特點

    語言編程,讓不懂代碼的人也可以快速搭建測試方案,讓測試測量更直觀、更簡單。本篇文章納米軟件Namisoft小編將為大家分享一下關于:對標Labview的國產測試工具神器ATECLOUD
    發表于 09-28 15:43 ?1615次閱讀
    國產<b class='flag-5'>測試</b>工具<b class='flag-5'>神器</b>ATECLOUD智能云<b class='flag-5'>測試</b>平臺技術特點

    Arthas -- 一款釋放潛力的神器

    阿里巴巴 Arthas 是一個診斷工具,可以用于監視、分析和解決 Java 應用程序的問題。使用 Arthas 的一個主要優點是,我們不需要修改代碼,甚至不需要重新啟動我們想要監視的 Java 服務。
    的頭像 發表于 07-05 11:21 ?597次閱讀
    <b class='flag-5'>Arthas</b> -- 一款釋放潛力的<b class='flag-5'>神器</b>

    基于Java的阿里巴巴Arthas調優方案

    在 main 方法中,我們使用一個循環和相對較大的數字,以便讓計算機進行較長時間的計算。這當然正是我們想要的,以便演示 Arthas
    發表于 07-05 11:19 ?157次閱讀
    基于Java的阿里巴巴<b class='flag-5'>Arthas</b>調優方案

    介紹一款基于java的滲透測試神器-CobaltStrike

    Cobalt Strike是一款基于java的滲透測試神器,常被業界人稱為CS神器
    的頭像 發表于 01-16 09:16 ?1083次閱讀
    介紹一款基于java的滲透<b class='flag-5'>測試</b><b class='flag-5'>神器</b>-CobaltStrike

    性能測試主要測什么 性能測試的指標有哪些

    性能測試是軟件測試的一個重要組成部分,主要用于評估軟件系統在各種負載條件下的性能表現。性能測試
    的頭像 發表于 05-29 15:42 ?2584次閱讀

    使用Arthas火焰圖工具的Java應用性能分析和優化經驗

    分享作者在使用Arthas火焰圖工具進行Java應用性能分析和優化的經驗。
    的頭像 發表于 10-28 09:27 ?361次閱讀
    使用<b class='flag-5'>Arthas</b>火焰圖工具的Java應用<b class='flag-5'>性能</b>分析和優化經驗

    華為云 X 實例 CPU 性能測試詳解與優化策略

    引言 ? 1. 測試環境搭建 ? 1.1 測試實例的選擇 ? 1.2 CPU性能測試工具介紹 ? 1.3 安裝和配置Sysbench ? 2. CPU
    的頭像 發表于 12-30 14:52 ?170次閱讀
    華為云 X 實例 CPU <b class='flag-5'>性能</b><b class='flag-5'>測試</b>詳解與優化策略
    主站蜘蛛池模板: 久久看精品 | 色婷婷婷丁香亚洲综合不卡 | 涩涩高清无乱码在线观看 | 天天舔天天操天天干 | 噜噜色小说 | 天天色综合社区 | 久久久免费视频播放 | 最近2018年中文字幕在线 | 二级黄绝大片中国免费视频0 | 日本高清免费一本视频在线观看 | 日本一区二区三区四区在线观看 | 黄色毛片大全 | 边做边爱在线观看视频免费 | 亚洲影院手机版777点击进入影院 | 欧美色欧美亚洲高清在线观看 | sese亚洲| 欧美色图在线观看 | 久久网站免费 | 欧美日韩无 | 美女露出扒开尿口让男人桶 | 在线 你懂 | 成年1314在线观看 | 五月亭亭免费高清在线 | 曰本aaaaa毛片午夜网站 | 国产精品你懂得 | 激情午夜婷婷 | 狠狠色丁香婷婷综合久久片 | 成人三级在线播放线观看 | 国产片无遮挡在线看床戏 | 欧美人另类zooz | videosgratis欧美另类老太 | 亚洲一区二区三区四 | 免费艹逼视频 | 日日舔夜夜操 | 伊人手机在线观看 | 欧美精品国产第一区二区 | 国产专区青青草原亚洲 | 加勒比视频网站 | 四虎影视永久在线精品免费播放 | 老色鬼久久综合第一 | 天天色踪合合 |