<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          更準確的測試Java程序性能——JMH基準測試

          共 1452字,需瀏覽 3分鐘

           ·

          2021-10-09 17:33

          什么是JMH

          JMH,即Java Microbenchmark Harness,Java平臺下的一套微基準測試工具。如果我們需要測試API性能的話,就可以用上這個工具,所以它并不是取代單元測試的。它可以在開發(fā)階段提供性能參考標準,不過這并不代表線上的性能表現(xiàn),不同的硬件和操作系統(tǒng)也會帶來性能差異,所以最終還是需要上到測試或沙箱環(huán)境,讓測試人員進行壓測。

          為什么需要JMH

          在了解JMH之前,如果需要性能測試,我們通常會使用for循環(huán),或者JMeter。而JMH正是比for循環(huán)嚴謹,比JMeter使用簡單的測試工具。

          再者,不知道你注意過沒有,在使用for循環(huán)測試時,第一次或者頭幾次運行總是最慢的,越到后面越快。從《計算機組成與設計 硬件軟件接口》一書中可以了解到,從更底層講,Java是解釋型的語言。雖然Java也需要編譯,但是編譯后只是字節(jié)碼,還需要JVM解釋成對應宿主機的機器碼。解釋的優(yōu)勢是可移植性,但是性能較差。在20世紀80和90年代,雖然解釋型語言的性能也飛速提升,但是與C語言相比,仍有10倍的性能差距。

          ?為了保持可移植性,同時又提高性能,Java便開發(fā)了即時編譯器(Just In Time complier),其通過記錄運行的程序來找到所謂的“熱點”方法,然后將它們直接編譯成宿主機的指令序列,即不通過JVM解釋那一層。這樣以后該方法的運行就會更快。

          看到這里也就明白了,為什么程序越到后面就會越快。JMH在真正的測試之前會預熱程序,而且還可以通過配置進程數(shù)、線程數(shù)等參數(shù)來使程序更接近實際的運行狀況。

          如何使用

          首先引入Maven依賴:

          ??????
          ????????????org.openjdk.jmh
          ????????????jmh-core
          ????????????1.21
          ????????

          ????????
          ????????????org.openjdk.jmh
          ????????????jmh-generator-annprocess
          ????????????1.21
          ????????????test
          ????????

          本案例中,我寫了一個簡單的小程序,它會從指定目錄讀取文件夾內容(每行一個數(shù)字),然后會對取出來的數(shù)字進行排序。排序算法選擇了插入排序和歸并排序,我們通過基準測試來看看兩者的性能差距。

          讀取文件內容

          public?class?ReadFile?{
          ???public?static?int[]?readInteger(String?path){
          ???????try(BufferedReader?in?=?new?BufferedReader(new?FileReader(path));)?{
          ???????????List?temp?=?new?ArrayList<>();
          ???????????String?str;
          ???????????while?((str?=?in.readLine())?!=?null)?{
          ???????????????temp.add(Integer.parseInt(str));
          ???????????}
          ???????????int[]?result?=?new?int[temp.size()];
          ???????????for(int?i=0;i???????????????result[i]=temp.get(i);
          ???????????}
          ???????????return?result;
          ???????}?catch?(Exception?e)?{
          ???????????e.printStackTrace();
          ???????????return?new?int[0];
          ???????}
          ???}
          }

          兩個排序算法就不貼了,網(wǎng)上可以搜到很多。實際的開發(fā)可能會用上SpringBoot,所以還得與Junit整合,并使用自動注入功能。先直接貼上測試代碼:

          @BenchmarkMode(Mode.All)
          @Warmup(iterations?=?3)//預熱輪數(shù)
          @Measurement(iterations?=?1,?time?=?1,?timeUnit?=?TimeUnit.SECONDS)
          @Threads(8)//線程數(shù)
          @Fork(0)?//fork的次數(shù),如果想用Autowired自動注入,這個填0
          @OutputTimeUnit(TimeUnit.MILLISECONDS)
          @State(Scope.Benchmark)
          @RunWith(SpringRunner.class)?//整合SpringBoot的測試運行環(huán)境
          @SpringBootTest
          public?class?JHMTest?{
          ???//想用自動注入功能,對象必須是靜態(tài)的,fork填0
          ????private?static?SortService?service;

          ????@Autowired
          ????void?setService(SortService?service){
          ????????JHMTest.service?=service;
          ????}

          ????@Test
          ????public?void?executeBenchmark()?throws?RunnerException?{
          ????????//JMH的選項配置,除了上面的注解方式的配置,也可以直接在這個Options里面配置。
          ???????//其中/Users/xxxx/Desktop/Benchmark.json是結果的輸出文件
          ????????Options?options?=?new?OptionsBuilder().include(this.getClass().getSimpleName())
          ????????????????.output("/Users/xxxx/Desktop/Benchmark.json").build();
          ????????new?Runner(options).run();
          ????}

          ????@Benchmark
          ????public?void?insertSortTest(){
          ????????int[]?arr?=?ReadFile.readInteger("/Users/xxxxx/Desktop/test.txt");
          ????????service.insertSort(arr);
          ????}

          ????@Benchmark
          ????public?void?mergeSortTest(){
          ????????int[]?arr?=?ReadFile.readInteger("/Users/xxxxx/Desktop/test?2.txt");
          ????????service.mergeSort(arr);
          ????}
          }

          上面注釋簡單寫了幾個關鍵點,我們執(zhí)行executeBenchmark方法,JMH就會執(zhí)行該類下帶有Benchmark注解的方法。最終結果會輸出到指定文件中

          其他注解的解釋可見圖

          結果查看

          打開結果文件,前面一大坨是系統(tǒng)信息,可以簡單看看,直接拉到最后,結果如下:

          Benchmark????????????????????????????????????????Mode?????Cnt????Score???Error???Units
          JHMTest.insertSortTest??????????????????????????thrpt??????????129.302??????????ops/ms
          JHMTest.mergeSortTest???????????????????????????thrpt??????????122.224??????????ops/ms
          JHMTest.insertSortTest???????????????????????????avgt????????????0.065???????????ms/op
          JHMTest.mergeSortTest????????????????????????????avgt????????????0.066???????????ms/op
          JHMTest.insertSortTest?????????????????????????sample??122410????0.066?±?0.002???ms/op
          JHMTest.insertSortTest:insertSortTest·p0.00????sample????????????0.014???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p0.50????sample????????????0.050???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p0.90????sample????????????0.106???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p0.95????sample????????????0.120???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p0.99????sample????????????0.192???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p0.999???sample????????????0.492???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p0.9999??sample???????????11.891???????????ms/op
          JHMTest.insertSortTest:insertSortTest·p1.00????sample???????????17.334???????????ms/op
          JHMTest.mergeSortTest??????????????????????????sample??122055????0.066?±?0.002???ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.00??????sample????????????0.014???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.50??????sample????????????0.050???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.90??????sample????????????0.107???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.95??????sample????????????0.121???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.99??????sample????????????0.187???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.999?????sample????????????0.457???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p0.9999????sample???????????11.957???????????ms/op
          JHMTest.mergeSortTest:mergeSortTest·p1.00??????sample???????????12.419???????????ms/op
          JHMTest.insertSortTest?????????????????????????????ss????????????0.020???????????ms/op
          JHMTest.mergeSortTest??????????????????????????????ss????????????0.020???????????ms/op

          結果如上,Mode中thrpt代表吞吐量,單位時間內的執(zhí)行次數(shù)。avgt是平均時間,一次執(zhí)行需要的單位時間。sample是基于采樣的執(zhí)行時間,采樣頻率由JMH自動控制。ss是單次執(zhí)行的時間。

          從結果上看,兩種排序算法的性能相差無幾,當然與我們的邏輯太簡單也有關系。這次的分享就到這里,大家趕緊用到自己的項目中,測試一下吧。


          ? 作者?|??耶low

          來源 |??cnblogs.com/lbhym/p/15363846.html

          加鋒哥微信:?java1239??
          圍觀鋒哥朋友圈,每天推送Java干貨!

          瀏覽 49
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  字幕一区二区三区四区五区在线看 | 夜夜拍拍| 小黄片在线免费观看 | 日日躁狠狠躁夜夜躁A片图片 | 永久免费 看片直接下载 |