簡體   English   中英

這個Java基准測試中發生了什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM