Java Micro-Benchmarking:如何編寫正確的基準

幾個月前,我寫了一篇文章比較循環的短索引的性能 。 我問自己關于使用短褲作為循環迭代次數很少的循環的性能。

在Java語言中,所有對整數的操作都是int進行的。 因此,如果我們使用short作為循環索引,則在每次迭代時都將進行類型轉換,這實際上比對int的簡單影響要重。

我編寫該代碼來實現我的目標:

package com.wicht.old;public class TestShortInt {public static void main(String[] args){long startTime = System.nanoTime();int resultInt = 0;for (int i = 0; i < 100000; i++){for (int j = 0; j < 32760; j++){resultInt += i * j;}}System.out.println("Temp pour int : " + (System.nanoTime() - startTime) / 1000000 + " ms");startTime = System.nanoTime();int resultShort = 0;for (int k = 0; k < 100000; k++){for (short f = 0; f < 32760; f++){resultShort += k * f;}}System.out.println("Temp pour short : " + (System.nanoTime() - startTime) / 1000000 + " ms");System.out.println(resultInt);System.out.println(resultShort);}
}

結果我發現short比int慢了兩倍,直到一周前我才確信這些結果。

這時,一位讀者(Jean)批評了我的測試結果,并給了我有關微基準測試的幾篇文章的鏈接。 我閱讀了這些文章,并了解了為什么我的結果不正確。

實際上,我的測試沒有注意可能改變測試結果的幾件事:

  • JVM預熱 :由于有幾個參數,代碼通常通常會很慢,并且隨著執行時間的增長直到達到穩態,代碼會變得越來越快。
  • 類加載 :第一次啟動基準測試時,必須加載所有使用的類,從而增加了執行時間。
  • 即時編譯器 :當JVM識別出代碼的重要部分時
  • 垃圾收集器 :在基準測試期間可能會發生垃圾收集,并且時間會大大增加。

由于所有這些因素,第一次運行(可能需要運行10秒)比其他運行速度慢,并且會使基準完全錯誤。

那么,我們如何才能取得良好的基準測試結果呢?

這確實很困難,但是我們可以使用Elliptic Group的軟件開發人員Brent Boyer引入的基準框架獲得幫助。 該框架照顧了所有先前引入的因素,并制定了良好的基準。

該框架的使用非常簡單,您只需創建Benchmark類的新實例,并將其傳遞給Callable或Runnable即可,然后直接啟動測試。 這是在循環索引中測試short和int的示例:

public class ShortIndexesLoop {public static void main(String[] args) {Callable callableInt = new Callable(){public Long call() throws Exception {long result = 0;for (int f = 0; f < 32760; f++){result += 444;}return result;}};Callable callableShort = new Callable(){public Long call() throws Exception {long result = 0;for (short f = 0; f < 32760; f++){result += 444;}return result;}};try {Benchmark intBenchmark = new Benchmark(callableInt);System.out.println("Result with int ");System.out.println(intBenchmark.toString());Benchmark shortBenchmark = new Benchmark(callableShort);System.out.println("Result short ");System.out.println(shortBenchmark.toString());} catch (Exception e) {e.printStackTrace();}}
}

要獲得結果,可以使用Benchmark.toString()或Benchmark.toStringFull()獲得更多統計信息。 您還可以使用Benchmark.getSd()直接訪問某些統計信息(例如標準差),也可以直接使用Benchmark.getStats()獲取所有統計信息。

這是前面代碼的結果:

結果int first = 807.056 us,平均值= 46.032 us(CI delta:-261.393 ns,+408.932 ns),sd = 230.929 us(CI delta:-68.201 us,+105.262 us)
結果短短優先= 721.912 us,平均值= 48.234 us(CI delta:-198.625 ns,+254.774 ns),sd = 160.196 us(CI delta:-32.764 us,+37.882 us)

如您所見,短版本僅比int慢104.78%。 這表明最初的結果是完全錯誤的。

這是int版本的完整結果:

動作統計信息:第一個= 807.056 us,平均值= 46.032 us(CI delta:-261.393 ns,+408.932 ns),sd = 230.929 us(CI delta:-68.201 us,+105.262 us)警告:執行時間有極端異常情況,標清值可能不準確---根據塊統計信息計算操作統計信息-每個塊測量32768個任務執行-用戶說任務內部執行m = 1個動作-那么每個塊測量的動作數為a = 32768-阻止統計信息:平均值= 1.508 s(CI增量:-8.565毫秒,+ 13.400毫秒),sd = 41.803毫秒(CI增量:-12.346毫秒,+ 19.054毫秒)–用于將阻止統計信息轉換為行動統計信息的論壇(均值)假設a / a為1 / s,則sd縮放為1 / sqrt(a))假定操作執行時間為iid — —每個置信區間(CI)被報告為點估計的+-增量或封閉點間隔([x,y])–每個置信區間的置信度為0.95 — —-–執行時間顯示在外邊的情況–使用箱線圖確定 中位數= 1.498 s,interquantileRange = 34.127 ms的算法– 3是極度(偏高):#57 = 1.621 s,#58 = 1.647 s,#59 = 1.688 s –2是溫和的(偏高): #55 = 1.570 s,#56 = 1.582 s ———-阻止sd值可能無法反映任務的內在變化–猜測:環境噪聲至少解釋了所測量sd的55.89418621876822%———- –動作sd值幾乎完全相同由離群值填充–根據等值離群值模型,它們至少導致了98.95646276911543%的已測量方差–模型數量:a = 32768.0,muB = 1.5083895562166663,sigmaB = 0.04180264914581472,muA = 4.603239612477619E-5,sigmaA = 2.3092919283255957E- 4,tMin = 0.0,muGMin = 2.3016198062388096E-5,sigmaG = 5.754049515597024E-6,cMax1 = 1252,cMax2 = 322,cMax = 322,cOutMin = 322,varOutMin = 0.0017292260645147487,muG(cOutMin)= 2.3034259031465023E-5, U(cOutMin)= 0.002363416110812895

就像您在使用此框架時可能看到的那樣,當您舉例說明您存在極端異常值可能使標準偏差完全錯誤時,它會向您發出一些警告。

您可以在Elliptic Group的網頁上下載此框架。 我發現它非常強大且易于使用,并且每次需要進行基準測試時都會使用它。

總而言之,我還必須說,即使您使用那種框架,如果您沒有測試代碼的正確部分,也可能會導致非常糟糕的基準測試。 這是來自Brent Boyer的兩篇非常有趣的文章:

  • 健壯的Java基準測試,第1部分:問題
  • 強大的Java基準測試,第2部分:統計信息和解決方案

參考: 如何通過 @Blog(“ Baptiste Wicht”)的 JCG合作伙伴 Baptiste Wicht 編寫正確的基準 。

相關文章 :
  • 績效焦慮–關于績效不可預測性,度量和基準
  • 改善Java應用程序性能的快速技巧
  • 如何在Java中獲得類似于C的性能
  • Java中的低GC:使用原語而不是包裝器
  • 如何在不到1ms的延遲內完成100K TPS

翻譯自: https://www.javacodegeeks.com/2011/09/java-micro-benchmarking-how-to-write.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374196.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374196.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374196.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

新唐M031學習筆記(一)定時器基礎計數應用

先上代碼 void Hw_Timer0_Init(void) {//20:100ms 200:10ms 2000:1ms 20000:100us 200000:10us TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 200000);/* Update prescale to set proper resolution. */TIMER_SET_PRESCALE_VALUE(TIMER0, 1); /* Enable Timer0 interrupt */TI…

java三元操作符注意

/* 三元操作符的類型務必一致 */ public class proposal_3 {public static void main(String[] args) {int i80;String sString.valueOf(i<90?90:100);String s1String.valueOf(i<90?90:100.0);if(s.equals(s1))System.out.println("s和s1相等&#xff01;"…

緩解口臭可以喝一種水

河南中醫學院第一附屬醫院耳鼻喉科主任醫師梅祥勝點評&#xff1a;通常情況下&#xff0c;口臭跟脾胃濕熱有關。中醫講&#xff1a;“胃主受納&#xff0c;脾主運化&#xff1b;胃氣主降&#xff0c;使飲食物及 其糟粕得以下行&#xff0c;脾氣主升&#xff0c;則飲食物之精華得…

asp.net+mvc+easyui+sqlite 簡單用戶系統學習之旅(二)—— easyui的簡單實用

下面開始在UserManager.Web中利用easyUI構建web。 1. 先刪除自帶的controllers、models和views&#xff08;里面的shared和web.config可以保存&#xff09;下面的文件 2. 要利用easyUI&#xff0c;首先去網上下載jquery-easyui-1.3.2.zip&#xff0c;同時下載一份EasyUI-1.3.2.…

adc如何獲取周期_LOL:千玨擁有ADC最需要的位移和無敵能力,為什么沒人用她打下路?...

— 點擊藍字 關注我們 —英雄聯盟自國服上線以來&#xff0c;已經陪伴玩家走過了9個年頭&#xff0c;目前英雄聯盟中的英雄數量已經達到了151位&#xff0c;每一位都各具特色。千玨是一位深受玩家們喜愛的英雄&#xff0c;其在官方英雄的定位中&#xff0c;屬于打野英雄&#x…

航順HK32F030MF4P6 RST作GPIO SWCLK作EXTI5 SWDIO作ADC_AIN0

老習慣&#xff0c;先上代碼 void Hw_Input_Chage_Init(void) {GPIO_InitTypeDef GPIO_InitStructure;RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_IOMUX, ENABLE);GPIOMUX->NRST_PIN_KEY (uint32_t)(0x00005AE1); //KEY…

centos7.2下編譯安裝git

centos最新的7.2版本&#xff0c;git居然是1.8&#xff0c;而最新的git版本是2.9 差的太多了&#xff0c;何況git2.0后有大更新。于是&#xff0c;我決定編譯安裝。中間有一點小破折&#xff0c;記錄一下&#xff0c;備忘。 1&#xff0c;下載最新的源碼&#xff0c;網址&#…

java務必讓常量的值在運行期保持不變

/* 常量就是常量&#xff0c;在編譯期就必須確定其值&#xff0c;不應該在運行期更改&#xff0c;否則程序的可讀性會非常差 */public class proposal_2 {interface Const{public static final int RAND_CONSTnew Random().nextInt();}public static void main(String[] arg…

Java并發教程–信號量

這是我們將要進行的Java并發系列的第一部分。 具體來說&#xff0c;我們將深入探討Java 1.5及更高版本中內置的并發工具。 我們假設您對同步和易失性關鍵字有基本的了解。 第一篇文章將介紹信號量-特別是對信號量進行計數 。 信號量是用于限制對資源訪問的經常被誤解和使用不足…

android surfaceview 大小_Android 使用Camera2 API采集視頻數據

Android 視頻數據采集系列的最后一篇出爐了&#xff0c;和前兩篇文章想比&#xff0c;這篇文章從系統API層面進行一些探索&#xff0c;涉及到的細節更多。初次接觸 Camera2 API 會覺得它的使用有些繁瑣&#xff0c;涉及到的類有些多&#xff0c;不過就像第一次使用Activity, Fr…

java生成隨機字符串

學習java comparable特性時候&#xff0c;定義如下Student類&#xff0c;需要需要隨機添加學生姓名以及學號和成績&#xff0c;這是java如何隨機生成名字&#xff0c;根據我的查詢&#xff0c;我找到目前java庫支持兩種方法。 1. org.apache.commons.lang3.RandomStringUtils類…

使用SharedPreferenes存取數據

//使用SharedPreference存儲數據 public void on(View view){     //獲取用戶名和密碼     String nameeditText1.getText().toString();     String numbereditText2.getText().toString();     //判斷checkBox是否為勾選      CheckBox box(CheckBox…

使用Java VisualVM分析您的應用程序

當您需要發現應用程序的哪個部分消耗更多的CPU或內存時&#xff0c;必須使用探查器執行此操作。 默認情況下&#xff0c;Sun JDK中附帶的一個探查器是Java VisualVM。 這個事件探查器非常簡單易用&#xff0c;功能強大。 在這篇文章中&#xff0c;我們將看到如何安裝它并使用它…

ArcSDE for SQL Server安裝及在ArcMap中創建ArcSDE連接

ArcSDE for SQL Server安裝及在ArcMap中創建ArcSDE連接 原文:ArcSDE for SQL Server安裝及在ArcMap中創建ArcSDE連接安裝ArcSDE for SQL Server&#xff0c;最后一步成功后的界面如下&#xff1a;在ArcMap中創建ArcSDE連接&#xff0c;截圖如下&#xff1a;posted on 2016-08-0…

java反射main方法參數注意

public class ReflectMethodMain {public static void main(String[] args) throws Exception {Method methodMainTestArgument.class.getMethod("main", String[].class);/*jdk 1.4之前的版本不支持可變參數&#xff0c;對組類的參數會自動拆包然后用來匹配數據參數…

python調用c函數傳字符串參數_Python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數...

在Python語言中&#xff0c;可以使用ctypes模塊調用其它如C語言編寫的動態鏈接庫DLL文件中的函數&#xff0c;在提高軟件運行效率的同時&#xff0c;也可以充分利用目前市面上各種第三方的DLL庫函數&#xff0c;以擴充Python軟件的功能及應用領域&#xff0c;減少重復編寫代碼、…

沁恒CH554 KEIL環境搭建

首先下載WCHISPTool_Setup.exe http://www.wch.cn/products/CH554.html 123這三個可下載的都下吧&#xff0c;后面開發都要用的 安裝好后運行&#xff0c;菜單欄上&#xff0c;功能->添加WCH MCU到KEIL器件庫 這時候在KEIL安裝目錄里面的UV4文件夾下可以看到wch.cdb的文件…

【CV論文閱讀】Rank Pooling for Action Recognition

這是期刊論文的版本&#xff0c;不是會議論文的版本。看了論文之后&#xff0c;只能說&#xff0c;太TM聰明了。膜拜~~ 視頻的表示方法有很多&#xff0c;一般是把它看作幀的序列。論文提出一種新的方法去表示視頻&#xff0c;用ranking function的參數編碼視頻的幀序列。它使用…

java不要在常量和變量中出現易混淆的字母

public class proposal {public static void main(String[] args) {long i1l; System.out.println("i的兩倍是&#xff1a;"(ii));System.out.println("i的兩倍是&#xff1a;"ii); //注意此處和上面的有很大的區別} }輸出&#xff1a;211/** 注意:* …

VS2019 WPF制作OTA上位機(一)新建工程

首先創建新項目&#xff0c;文件 -> 新建 -> 項目 下拉菜單選擇C#和Window&#xff0c;選擇WPF應用程序&#xff0c;下一步 輸入項目名&#xff0c;下一步 這里選擇.NET 5.0&#xff0c;也可以選擇其他的&#xff0c;個人習慣.NET&#xff0c;點擊創建 這時候出現初始…