精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

JMH性能測(cè)試,試試你代碼的性能如何

開(kāi)發(fā) 后端
最近在研究一些基礎(chǔ)組件實(shí)現(xiàn)的時(shí)候遇到一個(gè)問(wèn)題,關(guān)于不同技術(shù)的運(yùn)行性能比對(duì)該如何去實(shí)現(xiàn)。

[[442787]]

最近在研究一些基礎(chǔ)組件實(shí)現(xiàn)的時(shí)候遇到一個(gè)問(wèn)題,關(guān)于不同技術(shù)的運(yùn)行性能比對(duì)該如何去實(shí)現(xiàn)。

什么是性能比對(duì)呢?

舉個(gè)簡(jiǎn)單的栗子🌰 來(lái)說(shuō):假設(shè)我們需要驗(yàn)證String,StringBuffer,StringBuilder三者在使用的時(shí)候,希望能夠通過(guò)一些測(cè)試來(lái)比對(duì)它們的性能開(kāi)銷(xiāo)。下邊我羅列出最簡(jiǎn)單的測(cè)試思路:

for循環(huán)比對(duì)

這種測(cè)試思路的特點(diǎn):簡(jiǎn)單直接 

  1. public class TestStringAppendDemo {  
  2.     public static void testStringAdd() {  
  3.         long begin = System.currentTimeMillis();  
  4.         String item = new String();  
  5.         for (int i = 0; i < 100000; i++) {  
  6.             itemitem = item + "-";  
  7.         }  
  8.         long end = System.currentTimeMillis();  
  9.         System.out.println("StringBuffer 耗時(shí):" + (end - begin) + "ms");  
  10.     }  
  11.     public static void testStringBufferAdd() {  
  12.         long begin = System.currentTimeMillis();  
  13.         StringBuffer item = new StringBuffer();  
  14.         for (int i = 0; i < 100000; i++) {  
  15.             itemitem = item.append("-");  
  16.         }  
  17.         long end = System.currentTimeMillis();  
  18.         System.out.println("StringBuffer 耗時(shí):" + (end - begin) + "ms");  
  19.     }  
  20.     public static void testStringBuilderAdd() {  
  21.         long begin = System.currentTimeMillis();  
  22.         StringBuilder item = new StringBuilder();  
  23.         for (int i = 0; i < 100000; i++) {  
  24.             itemitem = item.append("-");  
  25.         }  
  26.         long end = System.currentTimeMillis();  
  27.         System.out.println("StringBuilder 耗時(shí):" + (end - begin) + "ms");  
  28.     }  
  29.     public static void main(String[] args) {  
  30.             testStringAdd();  
  31.             testStringBufferAdd();  
  32.             testStringBuilderAdd();  
  33.     }  

不知道你在平時(shí)工作中是否經(jīng)常會(huì)這么做,雖然說(shuō)通過(guò)簡(jiǎn)單的for循環(huán)執(zhí)行來(lái)看,我們確實(shí)能夠較好地給出誰(shuí)強(qiáng)誰(shuí)弱的這種結(jié)論,但是比對(duì)的結(jié)果并不精準(zhǔn)。因?yàn)镴ava程序的運(yùn)行時(shí)有可能會(huì)越跑越快的!

代碼越跑越快

看到這里你可能會(huì)有些疑惑,Java程序不是在啟動(dòng)之前都編譯成了統(tǒng)一的字節(jié)碼么,難道在字節(jié)碼翻譯為機(jī)器代碼的過(guò)程中還有什么不為人知的優(yōu)化處理手段?

下邊我們來(lái)觀察這么一段測(cè)試程序: 

  1. public static void testStringAdd() {  
  2.         long begin = System.currentTimeMillis();  
  3.         String item = new String();  
  4.         for (int i = 0; i < 100000; i++) {  
  5.             itemitem = item + "-";  
  6.         }  
  7.         long end = System.currentTimeMillis();  
  8.         System.out.println("String 耗時(shí):" + (end - begin) + "ms");  
  9.     }  
  10.     //循環(huán)20次執(zhí)行同一個(gè)方法  
  11.     public static void main(String[] args) {  
  12.         for(int i=0;i<20;i++){  
  13.             testStringAdd();  
  14.         }  
  15.     } 

執(zhí)行的程序耗時(shí)打印在了控制臺(tái)上:

20次的重復(fù)調(diào)用之后,發(fā)現(xiàn)首次和最后一次調(diào)用幾乎存在5倍的差異。看來(lái)代碼運(yùn)行越跑越快是存在的了,但是為什么會(huì)有這種現(xiàn)象發(fā)生呢?

這里我們需要了解一項(xiàng)叫做JIT的技術(shù)。

JIT技術(shù)

在介紹JIT技術(shù)之前,需要先進(jìn)行些相關(guān)知識(shí)的補(bǔ)充鋪墊。

解釋型語(yǔ)言

解釋型語(yǔ)言,是在運(yùn)行的時(shí)候才將程序翻譯成 機(jī)器語(yǔ)言 。解釋型語(yǔ)言的程序不需要在運(yùn)行前提前做編譯工作,在運(yùn)行程序的時(shí)候才翻譯,解釋器負(fù)責(zé)在每個(gè)語(yǔ)句執(zhí)行的時(shí)候解釋程序代碼。這樣解釋型語(yǔ)言每執(zhí)行一次就要“翻譯”一次,效率比較低。代表語(yǔ)言:PHP。

編譯型語(yǔ)言

在程序執(zhí)行之前,提前就將程序編譯成機(jī)器代碼,這樣后續(xù)機(jī)器在運(yùn)行的時(shí)候就不需要額外去做翻譯的工作,效率會(huì)相對(duì)較高。語(yǔ)言代表:C,C++。

而我們本文重點(diǎn)研究的是Java語(yǔ)言,我個(gè)人認(rèn)為這是一門(mén)既具備解釋特點(diǎn)又具備編譯特點(diǎn)的高級(jí)語(yǔ)言。

JVM是Java一次編譯,跨平臺(tái)執(zhí)行的基礎(chǔ)。當(dāng)Java被編譯為字節(jié)碼形式的.class文件之后,他可以在任意的JVM上運(yùn)行。

PS: 這里說(shuō)的編譯,主要是指前端編譯器。

前端編譯器

將.java文件編譯為JVM可執(zhí)行的.class字節(jié)碼文件,即javac,主要職責(zé)包括:詞法、語(yǔ)法分析,填充符號(hào)表,語(yǔ)義分析,字節(jié)碼生成。輸出為字節(jié)碼文件,也可以理解為是中間表達(dá)形式(稱(chēng)為IR:Intermediate Representation)。這時(shí)候的編譯結(jié)果就是我們常見(jiàn)的xxx.class文件。

后端編譯器

在程序運(yùn)行期間將字節(jié)碼轉(zhuǎn)變成機(jī)器碼,通過(guò)前端編譯器和后端編譯器的組合使用,通常就是被我們稱(chēng)之為混合模式,如 HotSpot 虛擬機(jī)自帶的解釋器還有 JIT(Just In Time Compiler)編譯器(分 Client 端和 Server 端),其中JIT還會(huì)將中間表達(dá)形式進(jìn)行一些優(yōu)化。

所以一份xxx.java的文件實(shí)際在執(zhí)行過(guò)程中會(huì)按照如下流程執(zhí)行,首先經(jīng)過(guò)前端解釋器轉(zhuǎn)換為.class格式的字節(jié)碼,再通過(guò)后端編譯器將其解釋為機(jī)器能夠識(shí)別的機(jī)器代碼。最后再由機(jī)器去執(zhí)行計(jì)算。

真的就這么簡(jiǎn)單嗎?

還記得我在上邊貼出的那段測(cè)試代碼嗎,首次執(zhí)行和最后執(zhí)行的性能差異如此巨大,其實(shí)是在后端編譯器處理的過(guò)程中加入優(yōu)化的手段。

在編譯時(shí),主要是將java源代碼文件編譯為統(tǒng)一的字節(jié)碼,但是編譯成的字節(jié)碼并不能直接運(yùn)行,而是需要通過(guò)JVM讀取運(yùn)行。JVM中的后端解釋器就是將.class文件一行一行翻譯之后再運(yùn)行,翻譯就是轉(zhuǎn)換成當(dāng)前機(jī)器可以運(yùn)行的機(jī)器碼,它不會(huì)一次性把整個(gè)文件都翻譯過(guò)來(lái),而是翻譯一句,執(zhí)行一句,再翻譯,再執(zhí)行,所以解釋器的程序運(yùn)行起來(lái)會(huì)比較慢,每次都要解釋之后再執(zhí)行。所以有些時(shí)候,我們想是否可以把解釋之后的內(nèi)容緩存起來(lái),這樣不就可以直接運(yùn)行了?但是,如果每段代碼都要緩存起來(lái),例如僅僅執(zhí)行一次的代碼也緩存起來(lái),這樣太浪費(fèi)內(nèi)存了。所以,引入一個(gè)新的運(yùn)行時(shí)編譯器,JIT來(lái)解決這些問(wèn)題,加速熱點(diǎn)代碼的執(zhí)行。

引入JIT技術(shù)之后,代碼的執(zhí)行過(guò)程是怎樣的?

在引入了JIT技術(shù)之后,一份Java程序的代碼執(zhí)行流程就會(huì)變成了下邊這種類(lèi)型。首先通過(guò)前端編譯器轉(zhuǎn)變?yōu)樽止?jié)碼文件,然后再判斷對(duì)應(yīng)的字節(jié)碼文件是否有被提前處理好存放在code cache中。如果有則可以直接執(zhí)行對(duì)應(yīng)的機(jī)器代碼,如果沒(méi)有則需要進(jìn)行判斷是否有必要進(jìn)行JIT技術(shù)優(yōu)化(判斷邏輯的細(xì)節(jié)后邊會(huì)講),如果有必要優(yōu)化,則會(huì)將優(yōu)化后的機(jī)器碼也存放到code cache中,否則則是會(huì)一邊執(zhí)行一邊翻譯為機(jī)器代碼。

怎樣的代碼才會(huì)被識(shí)別為熱點(diǎn)代碼呢?

在JVM中會(huì)設(shè)置一個(gè)閾值,當(dāng)某段代碼塊在一定時(shí)間內(nèi)被執(zhí)行的次數(shù)超過(guò)了這個(gè)閾值,則會(huì)被存放進(jìn)code cache中。

如何驗(yàn)證:

建立一個(gè)測(cè)試用的代碼Demo,然后設(shè)置JVM參數(shù):

-XX:CompileThreshold=500 -XX:+PrintCompilation 

  1. public class TestCountDemo {  
  2.     public static void test() {  
  3.         int a = 0 
  4.     }  
  5.    public static void main(String[] args) throws InterruptedException {  
  6.         for (int i = 0; i < 600; i++) {  
  7.             test();  
  8.         }  
  9.         TimeUnit.SECONDS.sleep(1);  
  10.     }  

接下來(lái)專(zhuān)心觀察啟動(dòng)程序之后的編譯信息記錄:

截圖解釋?zhuān)?/strong>

第一列693表示系統(tǒng)啟動(dòng)到編譯完成時(shí)的毫秒數(shù)。

第二列43表示編譯任務(wù)的內(nèi)部ID,一般是一個(gè)自增的值。

第三列為空,描述代碼狀態(tài)的5個(gè)屬性。

  •  %:是一個(gè)OSR(棧上替換)。
  •  s:是一個(gè)同步方法。
  •  !:方法有異常處理塊。
  •  b:阻塞模式編譯。
  •  n:是本地方法的一個(gè)包裝。

第四列3表示編譯級(jí)別,0表示沒(méi)有編譯而是使用解釋器,1,2,3表示使用C1編譯器(client),4表示使用C2編譯器(server),級(jí)別越高編譯生成的機(jī)器碼質(zhì)量越好,編譯耗時(shí)也越長(zhǎng)。

最后一列表示了方法的全限定名和方法的字節(jié)碼長(zhǎng)度。

從實(shí)驗(yàn)來(lái)看,當(dāng)for循環(huán)的次數(shù)一旦超過(guò)了預(yù)期設(shè)置的閾值,則會(huì)提前使用后端編譯器將代碼緩存到code cache中。

即時(shí)編譯極大地提高了Java程序的運(yùn)行速度,而且跟靜態(tài)編譯相比,即時(shí)編譯器可以選擇性地編譯熱點(diǎn)代碼,省去了很多編譯時(shí)間,也節(jié)省很多的空間。目前,即時(shí)編譯器已經(jīng)非常成熟了,在性能層面甚至可以和編譯型語(yǔ)言相比。不過(guò)在這個(gè)領(lǐng)域,大家依然在不斷探索如何結(jié)合不同的編譯方式,使用更加智能的手段來(lái)提升程序的運(yùn)行速度。

還記得我在文章開(kāi)頭所提出的幾個(gè)問(wèn)題嗎~~既然我們了解了Jvm底層具備了這些優(yōu)化的技能,那么如何才能更加準(zhǔn)確高效地去檢測(cè)一段程序的性能呢?

基于JMH來(lái)實(shí)踐代碼基準(zhǔn)測(cè)試

JMH是Java Microbenchmark Harness的簡(jiǎn)稱(chēng),一個(gè)針對(duì)Java做基準(zhǔn)測(cè)試的工具,是由開(kāi)發(fā)JVM的那群人開(kāi)發(fā)的。想準(zhǔn)確的對(duì)一段代碼做基準(zhǔn)性能測(cè)試并不容易,因?yàn)镴VM層面在編譯期、運(yùn)行時(shí)對(duì)代碼做很多優(yōu)化,但是當(dāng)代碼塊處于整個(gè)系統(tǒng)中運(yùn)行時(shí)這些優(yōu)化并不一定會(huì)生效,從而產(chǎn)生錯(cuò)誤的基準(zhǔn)測(cè)試結(jié)果,而這個(gè)問(wèn)題就是JMH要解決的。

關(guān)于如何使用JMH在網(wǎng)上有很多的講解案例,這些入門(mén)的資料大家可以自行去搜索。本文主要講解在使用JMH測(cè)試的時(shí)候需要注意到的一些細(xì)節(jié)點(diǎn):

常用的基本注解以及其具體含義

一般我們會(huì)將測(cè)試所使用的注解都標(biāo)注在測(cè)試類(lèi)的頭部,常用到的測(cè)試注解有以下幾種: 

  1. /**  
  2.  * 吞吐量測(cè)試 可以獲取到指定時(shí)間內(nèi)的吞吐量  
  3.  *  
  4.  * Throughput 可以獲取一秒內(nèi)可以執(zhí)行多少次調(diào)用  
  5.  * AverageTime 可以獲取每次調(diào)用所消耗的平均時(shí)間  
  6.  * SampleTime 隨機(jī)抽樣,隨機(jī)抽取結(jié)果的分布,最終是99%%的請(qǐng)求在xx秒內(nèi)  
  7.  * SingleShotTime 只允許一次,一般用于測(cè)試?yán)鋯?dòng)的性能  
  8.  */  
  9. @BenchmarkMode(Mode.Throughput) 
  10. /**  
  11.  * 如果一段程序被調(diào)用了好幾次,那么機(jī)器就會(huì)對(duì)其進(jìn)行預(yù)熱操作,  
  12.  * 為什么需要預(yù)熱?因?yàn)?nbsp;JVM 的 JIT 機(jī)制的存在,如果某個(gè)函數(shù)被調(diào)用多次之后,JVM 會(huì)嘗試將其編譯成為機(jī)器碼從而提高執(zhí)行速度。所以為了讓 benchmark 的結(jié)果更加接近真實(shí)情況就需要進(jìn)行預(yù)熱。  
  13.  */  
  14. @Warmup(iterations = 3 
  15. /**  
  16.  * iterations 每次測(cè)試的輪次  
  17.  * time 每輪進(jìn)行的時(shí)間長(zhǎng)度  
  18.  * timeUnit 時(shí)長(zhǎng)單位  
  19.  */  
  20. @Measurement(iterations = 10time = 5timeUnit = TimeUnit.SECONDS)  
  21. /**  
  22.  * 測(cè)試的線(xiàn)程數(shù),一般是cpu*2  
  23.  */  
  24. @Threads(8)  
  25. /**  
  26.  * fork多少個(gè)進(jìn)程出來(lái)測(cè)試  
  27.  */  
  28. @Fork(2)  
  29. /**  
  30.  * 這個(gè)比較簡(jiǎn)單了,基準(zhǔn)測(cè)試結(jié)果的時(shí)間類(lèi)型。一般選擇秒、毫秒、微秒。  
  31.  */  
  32. @OutputTimeUnit(TimeUnit.MILLISECONDS) 

如果不喜歡使用注解的方式也可以通過(guò)在啟動(dòng)入口中通過(guò)硬編碼的形式設(shè)置: 

  1. public static void main(String[] args) throws RunnerException {  
  2.         //配置進(jìn)行2輪熱數(shù) 測(cè)試2輪 1個(gè)線(xiàn)程  
  3.         //預(yù)熱的原因 是JVM在代碼執(zhí)行多次會(huì)有優(yōu)化  
  4.         Options options = new OptionsBuilder().warmupIterations(2).measurementBatchSize(2)  
  5.                 .forks(1).build();  
  6.         new Runner(options).run();  
  7.     } 

如果要對(duì)某項(xiàng)方法進(jìn)行JMH測(cè)試的話(huà),通常會(huì)對(duì)該方法的頭部加入@Benchmark注解。例如下邊這段: 

  1. @Benchmark  
  2.     public String testJdkProxy() throws Throwable {  
  3.         String content = dataService.sendData("test");  
  4.         return content;  
  5.     } 

JMH的一些坑

所有方法都應(yīng)該要有返回值

例如這么一段測(cè)試案例: 

  1. package org.idea.qiyu.framework.jmh.demo;  
  2. import org.openjdk.jmh.annotations.*;  
  3. import org.openjdk.jmh.runner.Runner;  
  4. import org.openjdk.jmh.runner.RunnerException;  
  5. import org.openjdk.jmh.runner.options.Options;  
  6. import org.openjdk.jmh.runner.options.OptionsBuilder;  
  7. import java.util.concurrent.TimeUnit;  
  8. import static org.openjdk.jmh.annotations.Mode.AverageTime;  
  9. import static org.openjdk.jmh.annotations.Mode.Throughput;  
  10. /**  
  11.  * JMH基準(zhǔn)測(cè)試  
  12.  */  
  13. @BenchmarkMode(Throughput)  
  14. @Fork(2)  
  15. @Warmup(iterations = 4 
  16. @Threads(4)  
  17. @OutputTimeUnit(TimeUnit.MILLISECONDS)  
  18. public class JMHHelloWord { 
  19.     @Benchmark  
  20.     public void baseMethod() {  
  21.     }  
  22.     @Benchmark  
  23.     public void measureWrong() {  
  24.         String item = "" 
  25.         itemitem = item + "s";  
  26.     }  
  27.     @Benchmark  
  28.     public String measureRight() {  
  29.         String item = "" 
  30.         itemitem = item + "s";  
  31.         return item;  
  32.     }  
  33.     public static void main(String[] args) throws RunnerException {  
  34.         Options options = new OptionsBuilder().  
  35.                 include(JMHHelloWord.class.getName()).  
  36.                 build();  
  37.         new Runner(options).run();  
  38.     }  

其實(shí)baseMethod和measureWrong兩個(gè)方法從代碼功能角度看來(lái),并沒(méi)有什么區(qū)別,因?yàn)檎{(diào)用它們兩者對(duì)于調(diào)用方本身并沒(méi)有造成什么影響,而且measureWrong函數(shù)中還存在著無(wú)用代碼塊,所以JMH會(huì)對(duì)內(nèi)部的代碼進(jìn)行“死碼消除”的處理。

通過(guò)測(cè)試會(huì)發(fā)現(xiàn),其實(shí)baseMethod和measureWrong的吞吐性結(jié)果差別不大。反而再比對(duì)measureWrong和measureRight兩個(gè)方法,后者只是加入了一個(gè)return關(guān)鍵字,JMH就能很好地去測(cè)算它的整體性能。

關(guān)于什么是“死碼消除”,我在這里貼出一段維基百科上的介紹,感興趣的讀者可以自行前往閱讀:

https://zh.wikipedia.org/wiki/%E6%AD%BB%E7%A2%BC%E5%88%AA%E9%99%A4

不要在Benchmark內(nèi)部加入循環(huán)的代碼

關(guān)于這一點(diǎn)我們可以通過(guò)一段案例來(lái)進(jìn)行測(cè)試,代碼如下: 

  1. package org.idea.qiyu.framework.jmh.demo;  
  2. import org.openjdk.jmh.annotations.*;  
  3. import org.openjdk.jmh.runner.Runner;  
  4. import org.openjdk.jmh.runner.RunnerException;  
  5. import org.openjdk.jmh.runner.options.Options;  
  6. import org.openjdk.jmh.runner.options.OptionsBuilder;  
  7. import java.util.concurrent.TimeUnit;  
  8. /**  
  9.  * @Author linhao  
  10.  * @Date created in 10:20 上午 2021/12/19  
  11.  */  
  12. @BenchmarkMode(Mode.AverageTime)  
  13. @Fork(1)  
  14. @Threads(4)  
  15. @Warmup(iterations = 1 
  16. @OutputTimeUnit(TimeUnit.MILLISECONDS)  
  17. public class ForLoopDemo {  
  18.     public int reps(int count) {  
  19.         int sum = 0
  20.         for (int i = 0; i < count; i++) {  
  21.             sumsum = sum + count;  
  22.         }  
  23.         return sum;  
  24.     }  
  25.     @Benchmark  
  26.     @OperationsPerInvocation(1)  
  27.     public int test_1() {  
  28.         return reps(1);  
  29.     }  
  30.     @Benchmark  
  31.     @OperationsPerInvocation(10)  
  32.     public int test_2() {  
  33.         return reps(10);  
  34.     }  
  35.     @Benchmark  
  36.     @OperationsPerInvocation(100)  
  37.     public int test_3() {  
  38.         return reps(100);  
  39.     }  
  40.     @Benchmark  
  41.     @OperationsPerInvocation(1000)  
  42.     public int test_4() {  
  43.         return reps(1000);  
  44.     }  
  45.     @Benchmark  
  46.     @OperationsPerInvocation(10000)  
  47.     public int test_5() {  
  48.         return reps(10000);  
  49.     }  
  50.     @Benchmark 
  51.     @OperationsPerInvocation(100000)  
  52.     public int test_6() {  
  53.         return reps(100000);  
  54.     }  
  55.     public static void main(String[] args) throws RunnerException {  
  56.         Options options = new OptionsBuilder()  
  57.                 .include(ForLoopDemo.class.getName())  
  58.                 .build();  
  59.         new Runner(options).run();  
  60.     }  

測(cè)試出來(lái)的結(jié)果顯示:

循環(huán)越多,反而得分越低,這一結(jié)果反而越來(lái)越不可信。

關(guān)于為什么在Benchmark中跑循環(huán)代碼會(huì)出現(xiàn)這類(lèi)不可信的情況,我在網(wǎng)上搜了一下技術(shù)文章,大致歸納為以下:

  •  循環(huán)展開(kāi)
  •  JIT & OSR 對(duì)循環(huán)的優(yōu)化

感興趣的朋友可以自行去深入了解,這里我就不做過(guò)多介紹了。

通過(guò)這個(gè)實(shí)驗(yàn)可以發(fā)現(xiàn),以后進(jìn)行Benchmark的性能測(cè)試過(guò)程中,盡量能不跑循環(huán)就不要跑循環(huán),如果真的要跑循環(huán),可以看下官方的這個(gè)用例:

https://github.com/lexburner/JMH-samples/blob/master/src/main/java/org/openjdk/jmh/samples/JMHSample_34_SafeLooping.java

Fork注解中的進(jìn)程數(shù)一定要大于0

這個(gè)是我通過(guò)實(shí)驗(yàn)發(fā)現(xiàn)的,如果設(shè)置為小于0的參數(shù)會(huì)發(fā)現(xiàn)跑出來(lái)的效果和預(yù)期的大大相反,具體原因還不太清楚。

測(cè)試結(jié)果報(bào)告的參數(shù)解釋

最后是關(guān)于如何閱讀JMH的測(cè)試報(bào)告,這里的這份報(bào)告是上邊講解的代碼案例中的測(cè)試結(jié)果。由于報(bào)告的內(nèi)容量比較大,所以這里只挑報(bào)告的結(jié)果來(lái)進(jìn)行講解: 

  1. Benchmark                   Mode  Cnt         Score        Error   Units  
  2. JMHHelloWord.baseMethod    thrpt   10  14343234.962 ± 585752.043  ops/ms  
  3. JMHHelloWord.measureRight  thrpt   10    260749.234 ±   5324.982  ops/ms  
  4. JMHHelloWord.measureWrong  thrpt   10    524449.863 ±   8330.106  ops/ms 

從報(bào)告的左往右開(kāi)始介紹起:

  •  Benchmark 就是對(duì)應(yīng)的測(cè)試方法。
  •  Mode 測(cè)試的模式。
  •  Cnt 循環(huán)了多少次。
  •  Score 是指測(cè)試的得分,這里因?yàn)檫x擇了以thrpt的模式進(jìn)行測(cè)試,所以分值越高表示吞吐率越高。
  •  Error 代表并不是表示執(zhí)行用例過(guò)程中出現(xiàn)了多少異常,而是指這個(gè)Score的精度可能存在誤差,所以前邊還有個(gè)± 的符號(hào)。

關(guān)于Error的解釋?zhuān)趕tackoverflow中也有解釋?zhuān)?/p>

https://codereview.stackexchange.com/questions/90886/jmh-benchmark-metrics-evaluation

如果你希望報(bào)告不是輸出在控制臺(tái),而是可以匯總到一份文檔中,可以通過(guò)啟動(dòng)指令去設(shè)置,例如: 

  1. public static void main(String[] args) throws RunnerException {  
  2.         Options options = new OptionsBuilder()  
  3.                 .include(StringBuilderBenchmark.class.getSimpleName())  
  4.                 .output("/Users/linhao/IdeaProjects/qiyu-framework-gitee/qiyu-framework/qiyu-framework-jmh/log/test.log")  
  5.                 .build();  
  6.         new Runner(options).run();  
  7.     }  

 

責(zé)任編輯:龐桂玉 來(lái)源: Java知音
相關(guān)推薦

2023-05-12 13:21:12

JMHJava程序

2021-07-08 14:59:05

JMHMongodb數(shù)據(jù)

2020-06-10 10:40:03

JavaJMH字符串

2021-03-18 07:52:42

代碼性能技巧開(kāi)發(fā)

2016-09-23 16:36:25

LinuxPCPhoronix

2025-01-27 11:52:23

2019-09-29 16:17:25

Java代碼性能編程語(yǔ)言

2013-06-27 10:34:08

準(zhǔn)備性能測(cè)試數(shù)據(jù)

2014-04-25 09:02:17

LuaLua優(yōu)化Lua代碼

2024-12-23 08:10:00

Python代碼性能代碼

2024-03-20 08:00:00

軟件開(kāi)發(fā)Java編程語(yǔ)言

2021-06-30 10:16:54

微服務(wù)架構(gòu)測(cè)試

2011-03-15 16:34:36

Iptables性能

2021-11-30 10:38:09

splitStringTokenJava

2013-08-15 14:10:24

云主機(jī)磁盤(pán)IO

2023-09-18 16:14:35

性能測(cè)試開(kāi)發(fā)

2013-12-25 10:32:41

MySQL性能測(cè)試

2013-05-08 09:31:32

MangoDB

2017-08-10 14:04:25

前端JavaScript函數(shù)性能

2021-07-03 08:54:49

LinuxSysbench性能
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

日本免费在线视频不卡一不卡二| 欧美男同视频网| 亚洲国产综合在线| 精品国产一区二区三区麻豆小说| 中文字幕在线欧美| 日韩理论电影大全| 欧美精品一区二区精品网| 无码人妻丰满熟妇区毛片18| seseavlu视频在线| 丁香婷婷综合五月| 国产精品日韩在线| 国产精品2020| 国产韩日影视精品| 国产视频精品免费播放| 亚洲妇熟xx妇色黄蜜桃| 伊人久久国产| 亚洲免费看黄网站| 日韩av电影免费播放| 亚洲第一精品网站| 蜜桃在线一区二区三区| 97在线视频免费观看| 日韩av片在线免费观看| 欧美夫妇交换xxx| av大全在线免费看| 成人激情综合网站| 成人久久久久久久| 99久久久久久久久| 极品尤物久久久av免费看| 日韩在线视频二区| 欧美bbbbb性bbbbb视频| 麻豆久久一区| 欧美日韩1区2区| 粗暴91大变态调教| 国模精品视频| 亚洲一区二区三区四区在线观看| 亚洲乱码国产乱码精品天美传媒| 亚洲三级黄色片| 国产91在线观看丝袜| 国产在线日韩在线| 男操女视频网站| 欧美资源在线| 8050国产精品久久久久久| 免费无遮挡无码永久在线观看视频| 日韩欧美一区二区三区在线视频| 日韩成人中文电影| 亚洲av成人精品一区二区三区 | 久久97久久97精品免视看秋霞| 欧美日韩国产系列| 在线免费视频a| 最新中文字幕在线播放| 污片在线观看一区二区| 99色这里只有精品| 成人免费网站观看| 同产精品九九九| 内射国产内射夫妻免费频道| heyzo高清在线| 婷婷一区二区三区| 波多野结衣综合网| 国产网站在线| 欧美日韩中文字幕日韩欧美| 男人日女人下面视频| 国产传媒在线观看| 午夜电影网一区| 欧美 日韩 国产在线观看| heyzo高清国产精品| 天天影视涩香欲综合网| 国产69精品久久久久999小说| missav|免费高清av在线看| 亚洲成人在线网站| 免费在线a视频| 91亚洲视频| 欧美欧美午夜aⅴ在线观看| 亚洲精品20p| 国产亚洲久久| 精品久久久久久久一区二区蜜臀| 美女伦理水蜜桃4| 欧美91在线| 亚洲欧美综合v| 国产精品成人在线视频| 亚洲成人国产| 久久久久久有精品国产| 日韩久久中文字幕| 久久se精品一区二区| 91青青草免费在线看| 隣の若妻さん波多野结衣| 99riav一区二区三区| 日本一区二区三区四区在线观看| 午夜毛片在线| 亚洲成a人片综合在线| 免费在线激情视频| 开心久久婷婷综合中文字幕| 精品国产伦一区二区三区观看方式 | 秋霞久久久久久一区二区| 岛国在线大片| 一区二区在线观看免费 | 国产精品一二三产区| 一本大道综合伊人精品热热 | 999国产精品亚洲77777| 欧美一区二区三区在线观看| 亚洲一区二区在线免费| 成人av国产| 高清欧美性猛交xxxx黑人猛交| 日韩中文字幕在线观看视频| 久久狠狠亚洲综合| 精品一区在线播放| 韩国中文字幕在线| 欧美性精品220| 欧美精品 - 色网| 免费久久久久久久久| 久热精品视频在线| 天天操夜夜操视频| 粉嫩一区二区三区在线看| 日本在线播放不卡| heyzo高清国产精品| 欧美精品 国产精品| 给我免费观看片在线电影的| 91九色精品| 热久久美女精品天天吊色| 国产视频手机在线观看| 久久久精品综合| 成年人网站国产| 亚洲综合资源| 伊人久久免费视频| 中文字幕亚洲精品在线| 国产高清精品久久久久| 亚洲第一综合| 大胆人体一区二区| 亚洲成年人影院在线| 国产麻豆a毛片| 日产国产高清一区二区三区 | 日韩精品不卡一区二区| 欧美一级大片在线观看| 丰满人妻一区二区三区四区53| 国产精品乱人伦一区二区| 国产乱子夫妻xx黑人xyx真爽| 深夜激情久久| 欧美超级乱淫片喷水| 夜夜嗨aⅴ一区二区三区| 91在线你懂得| 亚洲国产成人精品无码区99| 免费精品一区| 欧美xxxx做受欧美| 国产乱码一区二区| 国产精品国产三级国产aⅴ中文 | 波多野结衣在线aⅴ中文字幕不卡| 在线视频不卡一区二区| 91精品店在线| 在线看日韩欧美| 波多野结衣午夜| 国产亚洲成aⅴ人片在线观看| 国产中文字幕免费观看| 亚洲v天堂v手机在线| 2019亚洲男人天堂| 肉丝一区二区| 色综合视频在线观看| 成人h动漫精品一区| 一本综合久久| 欧美18视频| 欧美va在线观看| 中文日韩在线观看| 亚洲无码久久久久久久| 亚洲欧洲精品一区二区三区| 中文字幕线观看| 国产精品精品国产一区二区| 91久久久久久久久久| 老司机福利在线视频| 91精品国产91综合久久蜜臀| 激情五月婷婷小说| 99精品1区2区| 国产一级不卡毛片| 久久密一区二区三区| 成人欧美一区二区三区黑人| 182tv在线播放| 亚洲国产另类 国产精品国产免费| 国产成人亚洲欧洲在线| 国产欧美日韩三级| 手机在线视频一区| 91久久亚洲| 日韩精品一区二区三区外面| 精品69视频一区二区三区| 欧美精品中文字幕一区| 色综合久久久久久| 欧美性猛交xxxx黑人交| 欧美黄色aaa| av电影天堂一区二区在线| 狠狠操精品视频| 最新精品国产| 欧美国产综合视频| 亚洲成人毛片| 97婷婷涩涩精品一区| 国产日产精品久久久久久婷婷| 51精品秘密在线观看| 日本亚洲色大成网站www久久| 国产日韩精品一区二区三区在线| 亚洲天堂伊人网| 国产农村妇女精品一二区| 一区二区三区四区视频在线| 91成人噜噜噜在线播放| 国产精品久久久久高潮| 欧美6一10sex性hd| 中文字幕日韩综合av| 免费av网站观看| 欧美日韩一二三区| 日韩三级av在线| 中文字幕在线不卡国产视频| 欧美bbbbb性bbbbb视频| 国产一区二区三区综合| 成熟老妇女视频| 欧美日韩三区| 亚洲三区四区| 亚洲免费成人av在线| 91av免费看| 另类一区二区| 日本欧美黄网站| 后进极品白嫩翘臀在线播放| 在线看福利67194| 涩涩视频在线观看免费| 欧美不卡一区二区三区| 在线观看国产黄| 欧美视频在线看| 国产精品变态另类虐交| 国产精品国产自产拍高清av | 成人羞羞动漫| 欧美日韩一区二区三区在线观看免| 欧洲大片精品免费永久看nba| 国产精品久久久亚洲| 国产资源在线观看入口av| 国产精品黄色| aa级大片欧美| 天天干天天玩天天操| 久久精品一区二区国产| 欧美一级片免费播放| 亚洲激情中文| 一区二区在线不卡| 精品久久网站| 欧美一区二区三区成人久久片| 麻豆国产欧美一区二区三区r| 91丝袜脚交足在线播放| 国产日韩在线观看视频| 成人啪啪免费看| av小说在线观看| 噜噜噜在线观看免费视频日韩 | 性久久久久久久久久久| 国产大陆精品国产| 91人妻一区二区三区| 韩国v欧美v日本v亚洲v| 一区二区免费av| 男人的天堂亚洲一区| 亚洲成色www.777999| 日韩激情在线观看| 日韩精品一区二区三区不卡| 久久一日本道色综合久久| 国产欧美高清在线| 久久免费黄色| 午夜免费一区二区| 日本视频在线一区| 国产福利在线免费| 国产乱子轮精品视频| 少妇献身老头系列| 成人妖精视频yjsp地址| 国模私拍在线观看| 久久免费精品国产久精品久久久久| 久久久久久久久久久国产精品| 久久综合狠狠综合久久综合88 | 色播五月激情五月| 国产一区二区福利视频| 亚洲一二三四五| 99国产精品视频免费观看| 欧美 变态 另类 人妖| 久久精品欧美一区二区三区麻豆| 高清国产在线观看| 亚洲色图都市小说| 国产一级片网址| 色婷婷精品大在线视频| 在线能看的av| 欧美色大人视频| xxxwww在线观看| 日韩高清av一区二区三区| 成年人视频在线观看免费| 久久最新资源网| 麻豆成全视频免费观看在线看| 欧美专区在线视频| 伊人久久大香| 国内一区二区在线视频观看| 禁断一区二区三区在线| 性欧美videosex高清少妇| 日韩精品免费| 日韩a级在线观看| 日韩va欧美va亚洲va久久| 性鲍视频在线观看| 91美女片黄在线| 精品人妻伦九区久久aaa片| 亚洲成人免费观看| 最近中文字幕免费在线观看| 精品精品欲导航| 1769在线观看| 97在线看福利| 91精品国产色综合久久不卡粉嫩| 国产亚洲自拍偷拍| 999精品色在线播放| 免费 成 人 黄 色| 国产一区二区网址| 精品无码国产污污污免费网站| 亚洲黄色尤物视频| 波多野结衣黄色| 亚洲高清av在线| 91极品在线| 国产精品久久网| 露出调教综合另类| 日本福利视频在线观看| 日本午夜一本久久久综合| 日本黄色录像片| 亚洲精品精品亚洲| 最新国产中文字幕| 日韩精品福利在线| 黑人精品视频| 亚洲最大的av网站| 不卡一区2区| aa在线免费观看| 处破女av一区二区| 成年人午夜剧场| 欧美日韩不卡视频| 成年人视频在线看| 国产不卡av在线| 蜜桃a∨噜噜一区二区三区| 成人免费观看在线| 国产一区二区中文字幕| 亚洲不卡的av| 欧美日韩日日骚| 黄色电影免费在线看| 欧美亚洲另类激情另类| 成人h动漫精品一区二区器材| 亚洲亚洲精品三区日韩精品在线视频 | 午夜精品久久久久久毛片| 日韩区国产区| 老牛影视一区二区三区| 亚洲精品理论片| 欧美色视频日本版| 性感美女一级片| 国产91成人video| 琪琪久久久久日韩精品| 青青草成人免费在线视频| 大陆成人av片| 日韩av片在线播放| 日韩av综合网站| 女人让男人操自己视频在线观看| 国产久一道中文一区| 亚洲国产一区二区精品专区| 无码人妻久久一区二区三区蜜桃| 一区二区三区精品在线观看| 成人av手机在线| 久久久久久国产精品美女| 成人春色在线观看免费网站| 3d动漫一区二区三区| 99久久婷婷国产| 性无码专区无码| 亚洲无限av看| 九九久久国产| 青草全福视在线| 粉嫩一区二区三区在线看| 日韩伦人妻无码| 国产偷国产偷亚洲清高网站| 亚洲精品国产嫩草在线观看| 亚洲一区二区三区加勒比| 精品无人区卡一卡二卡三乱码免费卡| 黄色录像一级片| 精品乱码亚洲一区二区不卡| 极品视频在线| 日韩精品久久久毛片一区二区| 久久99国产精品久久99| 久久久久成人精品无码| 亚洲国产小视频| 日韩av免费| 老司机午夜网站| www.色精品| 最近中文字幕在线观看视频| 理论片在线不卡免费观看| 操欧美女人视频| 无码人妻丰满熟妇区五十路百度| 国产亚洲精品aa午夜观看| 91精品国产乱码久久| 欧美国产日韩一区二区三区| 亚洲动漫精品| 中文字幕中文在线| 偷窥少妇高潮呻吟av久久免费| 成人av一区| 国产成人亚洲欧美| 日韩中文字幕区一区有砖一区 | 136国产福利精品导航网址| 一本加勒比北条麻妃| 欧美日韩不卡一区| 国产激情视频在线看| 视频一区二区综合| 成人午夜电影小说| 国产亚洲久一区二区| 久久人91精品久久久久久不卡| 精品国产一区二区三区久久久樱花| 在线免费看v片| 91精品91久久久中77777| 影音先锋在线视频|