一起來了解一下針對代碼級別的性能測試工具 JMH吧滔迈!

正文開始

JMH,即Java Microbenchmark Harness什乙,這是專門用于進行代碼的微基準測試的一套工具API客冈。

JMH 由 OpenJDK/Oracle 里面那群開發(fā)了 Java 編譯器的大牛們所開發(fā) 。何謂 Micro Benchmark 呢稳强? 簡單地說就是在 method 層面上的 benchmark场仲,精度可以精確到微秒級。

Java的基準測試需要注意的幾個點:

  • 測試前需要預熱退疫。

  • 防止無用代碼進入測試方法中渠缕。

  • 并發(fā)測試。

  • 測試結(jié)果呈現(xiàn)褒繁。

比較典型的使用場景:

  1. 當你已經(jīng)找出了熱點函數(shù)亦鳞,而需要對熱點函數(shù)進行進一步的優(yōu)化時,就可以使用 JMH 對優(yōu)化的效果進行定量的分析棒坏。

  2. 想定量地知道某個函數(shù)需要執(zhí)行多長時間燕差,以及執(zhí)行時間和輸入 n 的相關(guān)性

  3. 一個函數(shù)有兩種不同實現(xiàn)(例如JSON序列化/反序列化有Jackson和Gson實現(xiàn)),不知道哪種實現(xiàn)性能更好

盡管 JMH 是一個相當不錯的 Micro Benchmark Framework坝冕,但很無奈的是網(wǎng)上能夠找到的文檔比較少徒探,而官方也沒有提供比較詳細的文檔,對使用造成了一定的障礙喂窟。 但是有個好消息是官方的 Code Sample 寫得非常淺顯易懂测暗, 推薦在需要詳細了解 JMH 的用法時可以通讀一遍——本文則會介紹 JMH 最典型的用法和部分常用選項央串。

第一個例子

添加maven依賴

如果使用maven項目,只需要添加如下依賴:

編寫性能測試

執(zhí)行方式

這個代碼里面有好多注解碗啄,你第一次見可能不知道什么意思质和。先不用管,我待會一一介紹稚字。

我們來運行這個測試饲宿,運行JMH基準測試有多種方式,一個是生成jar文件執(zhí)行胆描, 一個是直接寫main函數(shù)或?qū)憜卧獪y試執(zhí)行褒傅。

一般對于大型的測試,需要測試時間比較久袄友,線程比較多的話,就需要去寫好了丟到linux程序里執(zhí)行霹菊, 不然本機執(zhí)行很久時間什么都干不了了剧蚣。

先編譯打包之后,然后執(zhí)行就可以了旋廷。當然在執(zhí)行的時候可以輸入-h參數(shù)來看幫助鸠按。

另外如果對于一些小的測試,比如我寫的上面這個小例子饶碘,在IDE里面就可以完成了目尖,丟到linux上去太麻煩。 這時候可以在里面添加一個main函數(shù)如下:

這里其實也比較簡單扎运,new個Options瑟曲,然后傳入要運行哪個測試,選擇基準測試報告輸出文件地址豪治,然后通過Runner的run方法就可以跑起來了洞拨。

報告結(jié)果

我們跑一下這個基準測試,完成后打開 E:/Benchmark.log负拟,結(jié)果如下:

仔細看烦衣,三大部分,第一部分是字符串用加號連接執(zhí)行的結(jié)果掩浙,第二部分是StringBuilder執(zhí)行的結(jié)果花吟,第三部分就是兩個的簡單結(jié)果比較。這里注意我們forks傳的2厨姚,所以每個測試有兩個fork結(jié)果衅澈。

前兩部分是一樣的,簡單說下谬墙。首先會寫出每部分的一些參數(shù)設(shè)置矾麻,然后是預熱迭代執(zhí)行(Warmup Iteration)纱耻, 然后是正常的迭代執(zhí)行(Iteration),最后是結(jié)果(Result)险耀。這些看看就好弄喘,我們最關(guān)注的就是第三部分, 其實也就是最終的結(jié)論甩牺。千萬別看歪了蘑志,他輸出的也確實很不爽,error那列其實沒有內(nèi)容贬派,score的結(jié)果是xxx ± xxx急但,單位是每毫秒多少個操作「惴Γ可以看到波桩,StringBuilder的速度還確實是要比String進行文字疊加的效率好太多。

注解介紹

好了请敦,當你對JMH有了一個基本認識后镐躲,現(xiàn)在來詳細解釋一下前面代碼中的各個注解含義。

@BenchmarkMode

基準測試類型侍筛。這里選擇的是Throughput也就是吞吐量萤皂。根據(jù)源碼點進去,每種類型后面都有對應的解釋匣椰,比較好理解裆熙,吞吐量會得到單位時間內(nèi)可以進行的操作數(shù)。

  • Throughput: 整體吞吐量禽笑,例如“1秒內(nèi)可以執(zhí)行多少次調(diào)用”入录。

  • AverageTime: 調(diào)用的平均時間,例如“每次調(diào)用平均耗時xxx毫秒”佳镜。

  • SampleTime: 隨機取樣纷跛,最后輸出取樣結(jié)果的分布,例如“99%的調(diào)用在xxx毫秒以內(nèi)邀杏,99.99%的調(diào)用在xxx毫秒以內(nèi)”

  • SingleShotTime: 以上模式都是默認一次 iteration 是 1s贫奠,唯有 SingleShotTime 是只運行一次。往往同時把 warmup 次數(shù)設(shè)為0望蜡,用于測試冷啟動時的性能唤崭。

  • All(“all”, “All benchmark modes”);

@Warmup

上面我們提到了,進行基準測試前需要進行預熱脖律。一般我們前幾次進行程序測試的時候都會比較慢谢肾, 所以要讓程序進行幾輪預熱,保證測試的準確性小泉。其中的參數(shù)iterations也就非常好理解了芦疏,就是預熱輪數(shù)冕杠。

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

@Measurement

度量笼痹,其實就是一些基本的測試參數(shù)。

  1. iterations 進行測試的輪次

  2. time 每輪進行的時長

  3. timeUnit 時長單位

都是一些基本的參數(shù)酪穿,可以根據(jù)具體情況調(diào)整凳干。一般比較重的東西可以進行大量的測試,放到服務(wù)器上運行被济。

@Threads

每個進程中的測試線程救赐,這個非常好理解,根據(jù)具體情況選擇只磷,一般為cpu乘以2经磅。

@Fork

進行 fork 的次數(shù)。如果 fork 數(shù)是2的話喳瓣,則 JMH 會 fork 出兩個進程來進行測試。

@OutputTimeUnit

這個比較簡單了赞别,基準測試結(jié)果的時間類型畏陕。一般選擇秒、毫秒仿滔、微秒惠毁。

@Benchmark

方法級注解,表示該方法是需要進行 benchmark 的對象崎页,用法和 JUnit 的 @Test 類似鞠绰。

@Param

屬性級注解,@Param 可以用來指定某項參數(shù)的多種情況飒焦。特別適合用來測試一個函數(shù)在不同的參數(shù)輸入的情況下的性能蜈膨。

@Setup

方法級注解,這個注解的作用就是我們需要在測試之前進行一些準備工作牺荠,比如對一些數(shù)據(jù)的初始化之類的翁巍。

@TearDown

方法級注解,這個注解的作用就是我們需要在測試之后進行一些結(jié)束工作休雌,比如關(guān)閉線程池灶壶,數(shù)據(jù)庫連接等的,主要用于資源的回收等杈曲。

@State

當使用@Setup參數(shù)的時候驰凛,必須在類上加這個參數(shù)胸懈,不然會提示無法運行。

State 用于聲明某個類是一個“狀態(tài)”恰响,然后接受一個 Scope 參數(shù)用來表示該狀態(tài)的共享范圍趣钱。 因為很多 benchmark 會需要一些表示狀態(tài)的類,JMH 允許你把這些類以依賴注入的方式注入到 benchmark 函數(shù)里渔隶。Scope 主要分為三種羔挡。

  1. Thread: 該狀態(tài)為每個線程獨享。

  2. Group: 該狀態(tài)為同一個組里面所有線程共享间唉。

  3. Benchmark: 該狀態(tài)在所有線程間共享绞灼。

關(guān)于State的用法,官方的 code sample 里有比較好的例子呈野。

第二個例子

再來看一個更常規(guī)一點性能測試的例子低矮,

計算 1 ~ n 之和,比較串行算法和并行算法的效率被冒,看 n 在大約多少時并行算法開始超越串行算法

首先定義一個表示這兩種實現(xiàn)的接口:

具體的兩種實現(xiàn)代碼我就不貼了军掂,主要說明一下串行算法和并行算法實現(xiàn)原理:

  • 串行算法:使用 for-loop 來計算 n 個正整數(shù)之和。

  • 并行算法:將所需要計算的 n 個正整數(shù)分成 m 份昨悼,交給 m 個線程分別計算出和以后蝗锥,再把它們的結(jié)果相加。

進行 benchmark 的代碼如下:

看到這里還沒過癮率触,那么就來群里與更多的大佬交流切磋技術(shù)终议,戳這里:咱們來一起抱團取暖,好嗎葱蝗?

我在自己的筆記本電腦上跑下來的結(jié)果穴张,總數(shù)在10000時并行算法不如串行算法, 總數(shù)達到100000時并行算法開始和串行算法接近两曼,總數(shù)達到1000000時并行算法所耗時間約是串行算法的一半左右皂甘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市悼凑,隨后出現(xiàn)的幾起案子偿枕,更是在濱河造成了極大的恐慌,老刑警劉巖户辫,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件益老,死亡現(xiàn)場離奇詭異,居然都是意外死亡寸莫,警方通過查閱死者的電腦和手機捺萌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人桃纯,你說我怎么就攤上這事酷誓。” “怎么了态坦?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵盐数,是天一觀的道長。 經(jīng)常有香客問我伞梯,道長玫氢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任谜诫,我火速辦了婚禮漾峡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喻旷。我一直安慰自己生逸,他們只是感情好,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布且预。 她就那樣靜靜地躺著槽袄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锋谐。 梳的紋絲不亂的頭發(fā)上遍尺,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天,我揣著相機與錄音涮拗,去河邊找鬼乾戏。 笑死,一個胖子當著我的面吹牛多搀,可吹牛的內(nèi)容都是我干的歧蕉。 我是一名探鬼主播灾部,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼康铭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赌髓?” 一聲冷哼從身側(cè)響起从藤,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锁蠕,沒想到半個月后夷野,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡荣倾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年悯搔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舌仍。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡妒貌,死狀恐怖通危,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灌曙,我是刑警寧澤菊碟,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站在刺,受9級特大地震影響逆害,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚣驼,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一魄幕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隙姿,春花似錦梅垄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至欲鹏,卻和暖如春机久,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赔嚎。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工膘盖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尤误。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓侠畔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親损晤。 傳聞我的和親對象是個殘疾皇子软棺,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • ?JMH,即Java Microbenchmark Harness尤勋,這是專門用于進行代碼的微基準測試的一套工具AP...
    SunnyMore閱讀 6,722評論 2 16
  • 性能測試這個話題非常龐大喘落,我們可以從網(wǎng)絡(luò)聊到操作系統(tǒng),再從操作系統(tǒng)聊到內(nèi)核最冰,再從內(nèi)核聊到你懷疑人生有木有瘦棋。 先拍幾...
    此魚不得水閱讀 4,727評論 1 13
  • 內(nèi)容已經(jīng)移動到這里[https://blog.csdn.net/WeiPeng2K/article/details...
    weipeng2k閱讀 4,001評論 0 6
  • 介紹 JMH,即Java Microbenchmark Harness暖哨,從名字就可以看出赌朋,這是專門用于進行代碼的微...
    OuZhencong閱讀 6,911評論 0 3
  • 摘要:# 使用JMH做Java微基準測試 在使用Java編程過程中,我們對于一些代碼調(diào)用的細節(jié)有多種編寫方式,但是...
    Java架構(gòu)師Carl閱讀 429評論 0 0