Java好奇的循环性能

时间:2012-09-18 15:08:01

标签: java performance random for-loop

在评估我的java代码时,我遇到了一个大问题。为了简化问题,我编写了以下代码,这些代码产生了同样的奇怪行为。重要的是方法run()和给定的双倍价值率。对于我的运行时测试(在main方法中),我将速率设置为0.5一次,另一次设置为1.0。使用值1.0时,if语句将在每次循环迭代中执行,并且值为0.5时,if语句将执行一半。出于这个原因,我预计第一种情况下运行时间会更长,但情况相反。 谁能解释一下这个现象?

主要结果:

Test mit rate = 0.5
Length: 50000000, IF executions: 25000856
Execution time was 4329 ms.
Length: 50000000, IF executions: 24999141
Execution time was 4307 ms.
Length: 50000000, IF executions: 25001582
Execution time was 4223 ms.
Length: 50000000, IF executions: 25000694
Execution time was 4328 ms.
Length: 50000000, IF executions: 25004766
Execution time was 4346 ms.
=================================
Test mit rate = 1.0
Length: 50000000, IF executions: 50000000
Execution time was 3482 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3572 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3529 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3479 ms.
Length: 50000000, IF executions: 50000000
Execution time was 3473 ms.

守则

public ArrayList<Byte> list = new ArrayList<Byte>();
public final int LENGTH = 50000000;

public PerformanceTest(){
    byte[]arr = new byte[LENGTH];
    Random random = new Random();
    random.nextBytes(arr);
    for(byte b : arr)
        list.add(b);
}

public void run(double rate){

    byte b = 0;
    int count = 0;

    for (int i = 0; i < LENGTH; i++) {

        if(getRate(rate)){
            list.set(i, b);
            count++;
        }
    }
    System.out.println("Length: " + LENGTH + ", IF executions: " + count);
}

public boolean getRate(double rate){
    return Math.random() < rate;
}

public static void main(String[] args) throws InterruptedException {
    PerformanceTest test = new PerformanceTest();

    long start, end;
    System.out.println("Test mit rate = 0.5");
    for (int i = 0; i < 5; i++) {
        start=System.currentTimeMillis();
        test.run(0.5);
        end = System.currentTimeMillis();
        System.out.println("Execution time was "+(end-start)+" ms.");

        Thread.sleep(500);
    }       
    System.out.println("=================================");
    System.out.println("Test mit rate = 1.0");      
    for (int i = 0; i < 5; i++) {
        start=System.currentTimeMillis();
        test.run(1.0);
        end = System.currentTimeMillis();
        System.out.println("Execution time was "+(end-start)+" ms.");
        Thread.sleep(500);
    }   
}

3 个答案:

答案 0 :(得分:10)

分支错误预测会在第一种情况下导致性能下降。虽然第二种情况做了一些工作但它有点直接,所以处理器可以很容易地预测下一步。有关详细信息,请参阅此Wikipedia page

尝试用0.7进行测试。如果我是正确的,那么性能将介于0.5和1.0之间。

答案 1 :(得分:9)

为了确认您正在看到分支错误预测as indicated in my comment的影响,我已经进行了一些测试。表显示了速率(运行方法的输入),执行的if的数量和运行时间。

0.0   0             1162
0.1   5,000,892     1204.25
0.2   10,002,410    1236.8
0.3   14,998,226    1264
0.4   19,996,983    1278
0.5   24,998,455    1305.5
0.6   29,998,879    1263.25
0.7   34,999,821    1232.25
0.8   39,999,414    1203.5
0.9   44,998,674    1202
1.0   50,000,000    1176.75

越接近0.5,您获得的分支误预测就越多(大约每次运行一次)。越接近0或1,您获得的分支预测就越准确(当速率为0或1时没有误预测。)

因为一张图片胜过千言万语:

enter image description here

答案 2 :(得分:0)

Why is processing a sorted array faster than an unsorted array?非常相似并且幕后有相同的原因。