[英]What is going on in this java benchmark?
我正在使用junit運行原始基准測試,如下所示:
@Test
public void testTime() throws Exception{
LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");
final int iterations = 1000000;
long start = System.nanoTime();
int sum = 0;
for(int i = 0; i < iterations; ++i){
Iterator<Item> it = loadout.iterator();
while( it.hasNext() ){
sum += it.next().getNumCriticalSlots();
}
}
long end = System.nanoTime();
long time_it = end - start;
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
for(Item item : loadout.getAllItems()){
sum += item.getNumCriticalSlots();
}
}
end = System.nanoTime();
long time_arrays = end - start;
System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
如果我設置iterations=1000000
那么我得到
它:792771504數組:1109215387差異:0.7147137637029551
非常一致,但是如果我將iterations=10000
設置iterations=10000
那么我得到
它:32365742數組:28902811差異:1.1198129482976587
波動很大。 diff參數的范圍是0.7到1.2
任何人都可以對這里發生的事情有所了解嗎? 我應該選擇哪種方法?
我真正基准的是幕后工作。 getAllItems
創建一個新的List<Item>
並通過使用addAll
從16 addAll
列表中獲取所有項目來填充它。 Iterator
方法不是構造此臨時列表,而是跟蹤當前正在迭代這16個子列表中的哪個,並具有使該16個子列表看起來像連續列表的邏輯。
由於要測試兩者的區別Iterator
,並使用增強的for循環(使用Iterator
在后台為你身后),那么你就錯了。 首先是因為JIT有足夠的時間來改進第二種方法的結果,而不是第一種方法,這里解釋了以下幾個其他原因: 如何用Java編寫正確的微基准? 。 通過執行以下操作,您可能會看到非常不同的結果(同樣是JIT的結果):
for
循環。 for
循環方法之前要執行。 獲得測試真實結果的最佳方法是將這些方法分為不同的方法,然后進行每種方法的測量(除了JVM預熱階段和上一個QA中涵蓋的其他內容)。 另外,我建議您不要重新發明輪子,而應使用基於JUnit的適當基准測試框架。 這是其中兩個:
基准測試的相關Q / A:
閱讀了Luiggi Mendoza的鏈接后,我將測試代碼重構如下:
@Test
public void testTime() throws Exception{
LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");
long start, end, sum;
final int iterations = 10000;
//WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
Iterator<Item> it = loadout.iterator();
while( it.hasNext() ){
sum += it.next().getNumCriticalSlots();
}
}
end = System.nanoTime();
//ENDOF WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
Iterator<Item> it = loadout.iterator();
while( it.hasNext() ){
sum += it.next().getNumCriticalSlots();
}
}
end = System.nanoTime();
long time_it = end - start;
// WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
for(Item item : loadout.getAllItems()){
sum += item.getNumCriticalSlots();
}
}
end = System.nanoTime();
// ENDOF WARMUP
start = System.nanoTime();
sum = 0;
for(int i = 0; i < iterations; ++i){
for(Item item : loadout.getAllItems()){
sum += item.getNumCriticalSlots();
}
}
end = System.nanoTime();
long time_arrays = end - start;
System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
現在,我得到一致的結果,即迭代器方法的執行速度約為getAllItems
方法的執行速度的0.7倍。 即使我更改測試順序,結果也是一致的,因此我相信他們可以進行此測試。
謝謝。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.