偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Jmh基準(zhǔn)測試,看我怎么用它來測試Mongodb的數(shù)據(jù)加載性能

開發(fā) 前端 MongoDB
最近我們這邊引入了mongodb,不過沒有實(shí)際上測試過性能如何,只是聽說讀寫比mysql快,你今天沒有什么排期,測試一下,然后今天內(nèi)給我個(gè)答案吧!

 [[410165]]

本文轉(zhuǎn)載自微信公眾號(hào)「稀飯下雪」,作者帥氣的小飯飯 。轉(zhuǎn)載本文請(qǐng)聯(lián)系稀飯下雪公眾號(hào)。

「主管小肥肥:」 最近我們這邊引入了mongodb,不過沒有實(shí)際上測試過性能如何,只是聽說讀寫比mysql快,你今天沒有什么排期,測試一下,然后今天內(nèi)給我個(gè)答案吧

「小飯飯:」 好的,接下來就是測試性能的一天了。

到了這里,可能大部分人的第一想法應(yīng)該是直接用這種方式:

  1. public void test() { 
  2.     long start = System.currentTimeMillis(); 
  3.     // 執(zhí)行邏輯 
  4.     long end = System.currentTimeMillis();   
  5.     System.out.println(end - start); 

no,我這次使用的是JMH

無論出自何種原因需要進(jìn)行性能評(píng)估,量化指標(biāo)總是必要的,那么如何量化呢?

這就需要我們的主角 JMH 登場了!

先給你們看個(gè)效果圖

性能對(duì)比圖

什么是JMH

JMH(Java Microbenchmark Harness)是用于代碼微基準(zhǔn)測試的工具套件,主要是基于方法層面的基準(zhǔn)測試,精度可以達(dá)到納秒級(jí)。

該工具是由 Oracle 內(nèi)部實(shí)現(xiàn) JIT 的大牛們編寫的,他們應(yīng)該比任何人都了解 JIT 以及 JVM 對(duì)于基準(zhǔn)測試的影響。

當(dāng)你定位到熱點(diǎn)方法,希望進(jìn)一步優(yōu)化方法性能的時(shí)候,就可以使用 JMH 對(duì)優(yōu)化的結(jié)果進(jìn)行量化的分析。

JMH 比較典型的應(yīng)用場景如下:

  • 想準(zhǔn)確地知道某個(gè)方法需要執(zhí)行多長時(shí)間,以及執(zhí)行時(shí)間和輸入之間的相關(guān)性
  • 對(duì)比接口不同實(shí)現(xiàn)在給定條件下的吞吐量
  • 查看多少百分比的請(qǐng)求在多長時(shí)間內(nèi)完成

下面我們以mongodb、hibernate、jdbc數(shù)據(jù)加載性能對(duì)比為例,使用 JMH 做基準(zhǔn)測試。

怎么做JMH基準(zhǔn)測試?

  • 加入依賴

因?yàn)?JMH 是 JDK9 自帶的,如果是 JDK9 之前的版本需要加入如下依賴:

  1. <dependency> 
  2.     <groupId>org.openjdk.jmh</groupId> 
  3.     <artifactId>jmh-core</artifactId> 
  4.     <version>1.29</version> 
  5. </dependency> 
  6. <dependency> 
  7.     <groupId>org.openjdk.jmh</groupId> 
  8.     <artifactId>jmh-generator-annprocess</artifactId> 
  9.     <version>1.29</version> 
  10. </dependency> 
  • 編寫基準(zhǔn)測試

接下來,創(chuàng)建一個(gè) JMH 測試類,具體代碼如下所示:

  1. @BenchmarkMode({Mode.AverageTime}) 
  2. @Warmup(iterations = 1, time = 5) 
  3. @Measurement(iterations = 3, time = 5) 
  4. @Threads(1) 
  5. @Fork(1) 
  6. @OutputTimeUnit(TimeUnit.MILLISECONDS) 
  7. @State(Scope.Benchmark) 
  8. public class ReadBenchMarks { 
  9.     @Benchmark 
  10.     public void loadMongoTemplate(){ 
  11.         // mongoTemplate數(shù)據(jù)加載 
  12.     } 
  13.  
  14.     @Benchmark 
  15.     public void loadMongoDriver(){ 
  16.         // mongoDriver數(shù)據(jù)加載 
  17.     } 
  18.  
  19.     @Benchmark 
  20.     public void loadHibernate(){ 
  21.         // hibernate數(shù)據(jù)加載 
  22.     } 
  23.  
  24.     @Benchmark 
  25.     public void loadJdbc(){ 
  26.         // jdbc數(shù)據(jù)加載 
  27.     } 
  28.  
  29.     public static void main(String[] args) throws RunnerException { 
  30.         Options options = new OptionsBuilder() 
  31.                 .include(ReadBenchMarks.class.getSimpleName()) 
  32.                 .output("db.log"
  33.                 .build(); 
  34.         new Runner(options).run(); 
  35.     } 

「核心關(guān)注點(diǎn):」

類上加了注解

  • 需要測試的方法用 @Benchmark 注解標(biāo)識(shí)
  • 啟動(dòng)的方式

這些注解的具體含義將在下面介紹。

大家有興趣可以看下官方提供的 jmh 示例 demo:http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/

  • 執(zhí)行基準(zhǔn)測試

準(zhǔn)備工作做好了,接下來,運(yùn)行代碼,等待片刻,測試結(jié)果就出來了

  1. # JMH version: 1.29 
  2. # VM version: JDK 1.8.0_251, Java HotSpot(TM) Client VM, 25.251-b08 
  3. # VM invoker: C:\soft\Java\jdk1.8.0_251\jre\bin\java.exe 
  4. # VM options: -javaagent:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\lib\idea_rt.jar=53895:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\bin -Dfile.encoding=UTF-8 
  5. # Blackhole mode: full + dont-inline hint 
  6. # Warmup: 2 iterations, 5 s each 
  7. # Measurement: 10 iterations, 5 s each 
  8. # Timeout: 10 min per iteration 
  9. # Threads: 1 thread, will synchronize iterations 
  10. # Benchmark mode: Average timetime/op 
  11. # Benchmark: com.db.jmh.write.WriteBenchMarks.writeHibernate 
  12. # Parameters: (info = 10031,1,5) 
  13.  
  14. # Run progress: 0.00% complete, ETA 00:06:00 
  15. # Fork: 1 of 1 
  16. # Warmup Iteration   1: 7.743 ms/op 
  17. # Warmup Iteration   2: 9.433 ms/op 
  18. Iteration   1: 7.854 ms/op 
  19. Iteration   2: 8.638 ms/op 
  20. Iteration   3: 8.579 ms/op 
  21. Iteration   4: 8.213 ms/op 
  22. Iteration   5: 8.843 ms/op 
  23. Iteration   6: 9.178 ms/op 
  24. Iteration   7: 7.739 ms/op 
  25. Iteration   8: 9.608 ms/op 
  26. Iteration   9: 10.152 ms/op 
  27. Iteration  10: 9.461 ms/op 
  28.  
  29. Result "com.db.jmh.write.WriteBenchMarks.writeHibernate"
  30.   8.827 ±(99.9%) 1.182 ms/op [Average] 
  31.   (minavgmax) = (7.739, 8.827, 10.152), stdev = 0.782 
  32.   CI (99.9%): [7.645, 10.008] (assumes normal distribution) 
  33.  
  34. # Run complete. Total time: 00:06:38 
  35.  
  36. REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on 
  37. why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial 
  38. experiments, perform baseline and negative tests that provide experimental control, make sure 
  39. the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts. 
  40. Do not assume the numbers tell you what you want them to tell. 
  41.  
  42. Benchmark                           (info)  Mode  Cnt   Score   Error  Units 
  43. WriteBenchMarks.writeHibernate   10031,1,5  avgt   10   8.827 ± 1.182  ms/op 
  44. WriteBenchMarks.writeHibernate   10032,5,6  avgt   10   8.783 ± 1.478  ms/op 
  45. WriteBenchMarks.writeHibernate  10033,5,20  avgt   10  12.574 ± 0.928  ms/op 
  46. WriteBenchMarks.writeMongo       10031,1,5  avgt   10   5.057 ± 0.358  ms/op 
  47. WriteBenchMarks.writeMongo       10032,5,6  avgt   10   7.392 ± 0.651  ms/op 
  48. WriteBenchMarks.writeMongo      10033,5,20  avgt   10  12.590 ± 0.795  ms/op 

下面對(duì)結(jié)果做下簡單說明:

  1. # JMH version: 1.29 
  2. # VM version: JDK 1.8.0_251, Java HotSpot(TM) Client VM, 25.251-b08 
  3. # VM invoker: C:\soft\Java\jdk1.8.0_251\jre\bin\java.exe 
  4. # VM options: -javaagent:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\lib\idea_rt.jar=53895:C:\soft\idea\IntelliJ IDEA Community Edition 2020.1.1\bin -Dfile.encoding=UTF-8 
  5. # Blackhole mode: full + dont-inline hint 
  6. # Warmup: 2 iterations, 5 s each 
  7. # Measurement: 10 iterations, 5 s each 
  8. # Timeout: 10 min per iteration 
  9. # Threads: 1 thread, will synchronize iterations 
  10. # Benchmark mode: Average timetime/op 
  11. # Benchmark: com.db.jmh.write.WriteBenchMarks.writeHibernate 
  12. # Parameters: (info = 10031,1,5) 

該部分為「測試的基本信息」,比如使用的 Java 路徑,預(yù)熱代碼的迭代次數(shù),測量代碼的迭代次數(shù),使用的線程數(shù)量,測試的統(tǒng)計(jì)單位等。

  1. # Warmup Iteration   1: 7.743 ms/op 
  2. # Warmup Iteration   2: 9.433 ms/op 

該部分為每一次熱身中的性能指標(biāo),預(yù)熱測試不會(huì)作為最終的統(tǒng)計(jì)結(jié)果。預(yù)熱的目的是「讓 JVM 對(duì)被測代碼進(jìn)行足夠多的優(yōu)化」,比如,在預(yù)熱后,被測代碼應(yīng)該得到了充分的 JIT 編譯和優(yōu)化。

  1. Iteration   1: 7.854 ms/op 
  2. Iteration   2: 8.638 ms/op 
  3. Iteration   3: 8.579 ms/op 
  4. Iteration   4: 8.213 ms/op 
  5. Iteration   5: 8.843 ms/op 
  6. Iteration   6: 9.178 ms/op 
  7. Iteration   7: 7.739 ms/op 
  8. Iteration   8: 9.608 ms/op 
  9. Iteration   9: 10.152 ms/op 
  10. Iteration  10: 9.461 ms/op 
  11.  
  12.  
  13. Result "com.db.jmh.write.WriteBenchMarks.writeHibernate"
  14.   8.827 ±(99.9%) 1.182 ms/op [Average] 
  15.   (minavgmax) = (7.739, 8.827, 10.152), stdev = 0.782 
  16.   CI (99.9%): [7.645, 10.008] (assumes normal distribution) 

該部分顯示測量迭代的情況,每一次迭代都顯示了當(dāng)前的執(zhí)行速率,即一個(gè)操作所花費(fèi)的時(shí),在進(jìn)行 10 次迭代后,進(jìn)行統(tǒng)計(jì)。

最后的測試結(jié)果如下所示:

  1. Benchmark                           (info)  Mode  Cnt   Score   Error  Units 
  2. WriteBenchMarks.writeHibernate   10031,1,5  avgt   10   8.827 ± 1.182  ms/op 
  3. WriteBenchMarks.writeHibernate   10032,5,6  avgt   10   8.783 ± 1.478  ms/op 
  4. WriteBenchMarks.writeHibernate  10033,5,20  avgt   10  12.574 ± 0.928  ms/op 
  5. WriteBenchMarks.writeMongo       10031,1,5  avgt   10   5.057 ± 0.358  ms/op 
  6. WriteBenchMarks.writeMongo       10032,5,6  avgt   10   7.392 ± 0.651  ms/op 
  7. WriteBenchMarks.writeMongo      10033,5,20  avgt   10  12.590 ± 0.795  ms/op 

看這些數(shù)據(jù)也能看出個(gè)大概,不過我不大可能直接將這個(gè)數(shù)據(jù)扔給老大, 因此用了以下兩個(gè)網(wǎng)站

  • JMH Visual Chart:http://deepoove.com/jmh-visual-chart/
  • JMH Visualizer:https://jmh.morethan.io/

生成了一開始看到的那張圖形化界面。

補(bǔ)充下,JMH 基礎(chǔ)

為了能夠更好地使用 JMH 的各項(xiàng)功能,下面對(duì) JMH 的基本概念進(jìn)行講解:

  • @BenchmarkMode

用來配置 Mode 選項(xiàng),可用于類或者方法上,這個(gè)注解的 value 是一個(gè)數(shù)組,可以把幾種 Mode 集合在一起執(zhí)行,如:@BenchmarkMode({Mode.SampleTime, Mode.AverageTime}),還可以設(shè)置為 Mode.All,即全部執(zhí)行一遍。

  1. Throughput:整體吞吐量,每秒執(zhí)行了多少次調(diào)用,單位為 ops/time
  2. AverageTime:用的平均時(shí)間,每次操作的平均時(shí)間,單位為 time/op
  3. SampleTime:隨機(jī)取樣,最后輸出取樣結(jié)果的分布
  4. SingleShotTime:只運(yùn)行一次,往往同時(shí)把 Warmup 次數(shù)設(shè)為 0,用于測試?yán)鋯?dòng)時(shí)的性能
  5. All:上面的所有模式都執(zhí)行一次
  • @State

通過 State 可以指定一個(gè)對(duì)象的作用范圍,JMH 根據(jù) scope 來進(jìn)行實(shí)例化和共享操作。@State 可以被繼承使用,如果父類定義了該注解,子類則無需定義。由于 JMH 允許多線程同時(shí)執(zhí)行測試,不同的選項(xiàng)含義如下:

  1. Scope.Benchmark:所有測試線程共享一個(gè)實(shí)例,測試有狀態(tài)實(shí)例在多線程共享下的性能
  2. Scope.Group:同一個(gè)線程在同一個(gè) group 里共享實(shí)例
  3. Scope.Thread:默認(rèn)的 State,每個(gè)測試線程分配一個(gè)實(shí)例

@OutputTimeUnit

為統(tǒng)計(jì)結(jié)果的時(shí)間單位,可用于類或者方法注解

  • @Warmup

預(yù)熱所需要配置的一些基本測試參數(shù),可用于類或者方法上。一般前幾次進(jìn)行程序測試的時(shí)候都會(huì)比較慢,所以要讓程序進(jìn)行幾輪預(yù)熱,保證測試的準(zhǔn)確性。參數(shù)如下所示:

  1. iterations:預(yù)熱的次數(shù)
  2. time:每次預(yù)熱的時(shí)間
  3. timeUnit:時(shí)間的單位,默認(rèn)秒
  4. batchSize:批處理大小,每次操作調(diào)用幾次方法
  • @Measurement

實(shí)際調(diào)用方法所需要配置的一些基本測試參數(shù),可用于類或者方法上,參數(shù)和 @Warmup 相同。

  • @Threads

每個(gè)進(jìn)程中的測試線程,可用于類或者方法上。

  • @Fork

進(jìn)行 fork 的次數(shù),可用于類或者方法上。如果 fork 數(shù)是 2 的話,則 JMH 會(huì) fork 出兩個(gè)進(jìn)程來進(jìn)行測試。

  • @Param

指定某項(xiàng)參數(shù)的多種情況,特別適合用來測試一個(gè)函數(shù)在不同的參數(shù)輸入的情況下的性能,只能作用在字段上,使用該注解必須定義 @State 注解。

在介紹完常用的注解后,讓我們來看下 JMH 有哪些陷阱。

回答個(gè)疑問,為什么需要預(yù)熱?

因?yàn)?JVM 的 JIT 機(jī)制的存在,如果某個(gè)函數(shù)被調(diào)用多次之后,JVM 會(huì)嘗試將其編譯為機(jī)器碼,從而提高執(zhí)行速度,所以為了讓 benchmark 的結(jié)果更加接近真實(shí)情況就需要進(jìn)行預(yù)熱。

如何將測試結(jié)果 可視化

其實(shí)很簡單,將main函數(shù)改成

  1. public static void main(String[] args) throws RunnerException { 
  2.     Options opt = new OptionsBuilder() 
  3.             .include(WriteBenchMarks.class.getSimpleName()) 
  4.             .result("db_read.json"
  5.             .resultFormat(ResultFormatType.JSON).build(); 
  6.     new Runner(opt).run(); 

就可以了,再將生成的json格式文件扔進(jìn)以下網(wǎng)站:

  • JMH Visual Chart:http://deepoove.com/jmh-visual-chart/
  • JMH Visualizer:https://jmh.morethan.io/

就可以了啦。

「小飯飯:」 我測完啦,還生成了柱形圖給你看看

「主管小肥肥:」 不錯(cuò),mongodb的性能確實(shí)ok,你做的也不錯(cuò),還以為你會(huì)用System.currentTimeMillis()這種low的手段呢,沒想到用上了JMH,做的不錯(cuò),快調(diào)薪了,必須給你加一筆。

原文鏈接:https://mp.weixin.qq.com/s/hTRa-eOSvSns0sm2P2BMVg

 

責(zé)任編輯:武曉燕 來源: 稀飯下雪
相關(guān)推薦

2023-10-20 11:24:25

JMH基準(zhǔn)測試

2021-12-29 10:30:15

JMH代碼Java

2023-07-31 09:13:13

ValidatorGolang

2016-09-23 16:36:25

LinuxPCPhoronix

2024-03-06 18:09:06

Linux性能工具

2021-07-17 15:25:05

PHP 8.1基準(zhǔn)測試開發(fā)

2009-10-10 11:11:40

服務(wù)器測試

2012-07-31 09:02:49

Apworks

2013-05-07 09:47:30

測試MySQLMySQL測試

2023-01-06 08:31:53

數(shù)據(jù)庫基準(zhǔn)測試

2011-09-27 10:11:14

MongoDBR

2011-03-03 10:32:07

Mongodb億級(jí)數(shù)據(jù)量

2022-03-29 11:48:40

Go泛型測試

2023-05-12 13:21:12

JMHJava程序

2023-10-08 16:28:36

數(shù)據(jù)庫DuckDB

2010-05-13 15:43:34

MySQL宣布

2015-05-19 16:52:13

企業(yè)網(wǎng)D1Net

2020-06-10 10:40:03

JavaJMH字符串

2022-07-06 09:29:40

JMH性能測試

2009-02-09 11:06:19

WindowsUbuntuWindows7
點(diǎn)贊
收藏

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