Java 9代码工具:使用Java微型基准测试工具的实践会话
用肉眼看,基準(zhǔn)測試似乎只是確定執(zhí)行某些代碼需要花費(fèi)多長時間的簡單問題。 但是通常,這是幼稚的方法。 提供具有準(zhǔn)確和可重復(fù)結(jié)果的有意義的基準(zhǔn)并非易事。
在本文中,我們想向您介紹OpenJDK代碼工具項目,尤其是JMH。 Java Microbenchmarking線束。 我們已經(jīng)意識到它已有一段時間了,但是當(dāng)我們看到它將在Java 9的開發(fā)中廣泛使用時,它再次引起了我們的注意。
基準(zhǔn)測試挑戰(zhàn)
那么,為什么t2-t1的普通計時樣式不起作用? 除非您正在監(jiān)視實時系統(tǒng),否則有許多因素可能會影響基準(zhǔn)測試結(jié)果并使它們無效。 如果您沒有使用像JMH這樣的標(biāo)準(zhǔn)化基準(zhǔn)測試工具,結(jié)果通常會令人懷疑。 并且不要忘記常識。 最重要的因素是常識 。
通常,問題是由特定的系統(tǒng)和VM優(yōu)化引起的,這些優(yōu)化可能會使結(jié)果在一個經(jīng)過測試的用例中傾斜,而在另一個測試用例中不起作用。 為了最好或最壞。 諸如意外的GC,預(yù)熱時間,消除死代碼,各種JIT編譯器優(yōu)化,運(yùn)行時差異,CPU怪癖等問題一直存在。 所有不一定與要進(jìn)行基準(zhǔn)測試的實際因素相關(guān)的因素。
哪個…是根據(jù)圖靈獎獲得者Donald Knuth的流行語錄創(chuàng)建的:
要更深入地了解JMH如何解決這些問題,請查看Aleksey Shipilev的演講和博客 。
JMH入門
設(shè)置您的項目使用JMH可以通過兩種方式完成,作為一個獨(dú)立項目,或者通過使用maven將依賴項添加為現(xiàn)有項目的一部分。 有關(guān)說明可在此處的官方頁面上找到 。 順便說一下,JMH還支持其他JVM語言,例如Scala,Groovy和Kotlin。
設(shè)置好環(huán)境后,就該移到實際的代碼了。 JMH是一個注釋驅(qū)動的框架,下面通過一個示例讓我們看看它的含義。
基準(zhǔn)測試示例:比較URL驗證
在此測試中,我們將比較兩種使用Java驗證URL的不同方法:
1.使用java.net.URL構(gòu)造函數(shù)。 如果構(gòu)造函數(shù)由于URL無效而失敗,則將引發(fā)MalformedURLException。 為了使測試更有趣,還添加了兩個變體,將堆棧跟蹤深度限制為6種方法,并完全取消了堆棧跟蹤。
2.使用正則表達(dá)式,至少可以說是一個非常可怕的正則表達(dá)式,穆哈哈。 如果該網(wǎng)址不符合該格式,則我們認(rèn)為該網(wǎng)址無效。
結(jié)果將幫助我們對這個問題有一個明確的答案,因此是時候下注了。 如果您在下面的評論部分中弄錯了,請告訴我們:)
怪物正則表達(dá)式! URL驗證模式。 它還活著!!!
非常感謝Hardy Ferentschik ,他讓我們與Takipi博客讀者分享了他的用例。 Hardy是RedHat的首席工程師,在Hibernate團(tuán)隊工作,還是Hibernate Validator的項目負(fù)責(zé)人。
基準(zhǔn)測試的完整源代碼可在GitHub上找到 。 我們建議在最接近的選項卡中將其打開,并將本節(jié)的其余部分用作參考手冊。
1.基準(zhǔn)設(shè)置
@BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 1) @Measurement(iterations = 2) @OutputTimeUnit(TimeUnit.NANOSECONDS)這是發(fā)生了什么的解釋:
 @BenchmarkMode 
 首先,選擇我們要使用的基準(zhǔn)測試模式。 JMH為我們提供了4種不同的模式: 吞吐量 , AverageTime , SampleTime (包括百分位數(shù))和SingleShotTime (一次運(yùn)行一個方法)。 這些的任何組合也是完全合法的。 
 @Warmup(迭代次數(shù)= 1) 
 預(yù)熱迭代次數(shù)。 
 @Measurement(迭代次數(shù)= 2) 
 實際測量迭代次數(shù)。 在此示例基準(zhǔn)測試中,我們進(jìn)行了2次迭代,然后取平均分。 
 @OutputTimeUnit(TimeUnit.NANOSECONDS) 
 輸出結(jié)果的時間單位,即對您有意義的java.util.concurrent.TimeUnit的任何值。 
2.基準(zhǔn)范圍–初始狀態(tài)
設(shè)置好之后,我們需要設(shè)置基準(zhǔn)的初始狀態(tài)。 在這種情況下,它包括我們將要測試的URL,正則表達(dá)式測試的類和URL構(gòu)造函數(shù)測試的類。
每個此類都應(yīng)使用@State(Scope.Benchmark)進(jìn)行注釋。
另外,對于URL列表,請注意@Param批注,用于將不同的值提供給基準(zhǔn):
@State(Scope.Benchmark)public static class URLHolder {@Param(value = {// should match"http://foo.com/blah_blah","http://142.42.1.1:8080/","http://例子.測試",// should not match"http//foo/","///a",":// should fail"})String url; }3.基準(zhǔn)代碼
現(xiàn)在我們已經(jīng)設(shè)置好配置和初始狀態(tài),我們可以前進(jìn)到實際的基準(zhǔn)代碼了。
@Benchmark @Fork(1) public boolean regExp(ValidateByRegExp validator, URLHolder urlHolder) {return validator.isValid( urlHolder.url ); } @基準(zhǔn) 
 將此方法標(biāo)記為基準(zhǔn)。 
 @叉(1) 
 要運(yùn)行的試驗次數(shù)。 每次運(yùn)行都在不同的JVM中開始。 通過此批注,您還可以提供要包含在測試中的JVM參數(shù)。 因此,對于有限的堆棧跟蹤測試,我們看到正在使用@Fork(value = 1,jvmArgs =“ -XX:MaxJavaStackTraceDepth = 6”) 。 
4.運(yùn)行測試
使用選項模式:
public static void main(String[] args) throws Exception {Options opt = new OptionsBuilder().include( ".*" + URLConstraintBenchmark.class.getSimpleName() + ".*" ).build();new Runner( opt ).run(); }**這絕不是一個完整的指南,只是一個快速的教程,可以幫助您熟悉這些概念。 有關(guān)完整的示例集,請在此處查看官方的OpenJDK示例代碼。
結(jié)果
如果您感到好奇,請以納秒為單位報告結(jié)果。 是時候看看您的賭注是否正確了。 前3個網(wǎng)址合法,后3個網(wǎng)址無效:
我們看到,如果這是一個有效的URL,則驗證的正則表達(dá)式非常糟糕。 在我們所有的有效網(wǎng)址中,它收到的效果最差。 另一方面,我們看到如果URL無效,則表將旋轉(zhuǎn),并且正則表達(dá)式將獲得最佳結(jié)果。
在URL構(gòu)造器方面,我們看不到有效URL的顯著差異。 每個變體都提供幾乎相同的結(jié)果,領(lǐng)先于正則表達(dá)式。 對于添加了MalformedURLException的無效URL,還有另一件事需要考慮:異常的堆棧跟蹤。 相對于干凈的(正則表達(dá)式)正則表達(dá)式版本,放慢了操作速度。
那么最好的選擇是什么? 假設(shè)您的大多數(shù)數(shù)據(jù)都包含有效的URL,則URL構(gòu)造函數(shù)的工作方式將是最好的。 盡管在某些情況下使用正則表達(dá)式可能會更好,但是如果您假設(shè)絕大多數(shù)URL都是無效的。
誰使用JMH對其代碼進(jìn)行基準(zhǔn)測試?
首先,JMH被構(gòu)建為OpenJDK項目的內(nèi)部代碼工具。 正如Oracle Java性能專家,JMH項目負(fù)責(zé)人Aleksey Shipilev告訴我們的那樣:
“ JMH摸索著自己的癢:OpenJDK本身的性能工作。 因此,我們有許多特定于功能的基準(zhǔn),用于評估開發(fā)中代碼的性能。 JMH驅(qū)動的基準(zhǔn)測試報告了許多性能錯誤,以展示我們所看到的行為,并提供簡單的測試用例來驗證JDK更改。”
正如我們所討論的那樣,由于基準(zhǔn)測試的準(zhǔn)確性主要取決于它如何處理系統(tǒng)行為的各種優(yōu)化和變化,因此沒有比OpenJDK團(tuán)隊更好的團(tuán)隊來構(gòu)建這種工具。 構(gòu)建JVM的團(tuán)隊相同,其中包括大多數(shù)有用的(至今還很難進(jìn)行基準(zhǔn)測試)優(yōu)化。
由于開發(fā)JMH的團(tuán)隊非常接近基礎(chǔ)VM,因此它比其他工具更受青睞,并且可以在許多Java和Scala庫和工具中使用。 一些著名的例子包括Twitter的Fingale和供生產(chǎn)使用 的其他 實用程序 , Jersey , Square Okio ,各種Apache項目,Hibernate等。
最后的想法
像許多其他核心Java問題一樣,當(dāng)涉及基準(zhǔn)測試時,OpenJDK團(tuán)隊和資源通常是尋找答案的最佳場所。 JMH是一種易于使用的替代方法,可替代自家種植(且大多數(shù)情況下是錯誤的)微基準(zhǔn)。 盡管這絕對不會使您擺脫常識來確保基準(zhǔn)正確! 我們希望您發(fā)現(xiàn)該資源有用,并將繼續(xù)探索使用JMH創(chuàng)建有意義的基準(zhǔn)并與Java社區(qū)共享您的發(fā)現(xiàn)。 本周,我們還要分享在塔基皮(Takipi)取得的一些新進(jìn)展。 如果您還沒有看到實際的效果,那么這里是您入門所需的一切 。
翻譯自: https://www.javacodegeeks.com/2015/11/java-9-code-tools-a-hands-on-session-with-the-java-microbenchmarking-harness.html
總結(jié)
以上是生活随笔為你收集整理的Java 9代码工具:使用Java微型基准测试工具的实践会话的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: java 反编译项目_Java 7 –反
 - 下一篇: 推荐组装电脑配置如何自配电脑