用不必要的条件快速编码?

时间:2016-09-23 15:38:58

标签: java optimization

我有以下java函数,用于计算两个排序数组中的公共元素。请注意带有问号的行。

public static int overlap(int[] a, int[] b)
{
    int i = 0, j = 0;

    int res = 0;

    while(i < a.length && j < b.length)
    {
        if(a[i] > b[j])
            j ++;
        else if(a[i] < b[j])
            i ++;
        else if(a[i] == b[j])  // ?
        {
            res ++;
            i ++;
            j ++;
        }
    }

    return res;
}

显然,最后一个if语句不需要存在:在那一点上我们知道这两个值是相等的。但是,当我测试速度时(我正在检查检查的顺序是否有所不同),使用多余检查的方法总是比没有检查的方法更快(有时是两倍)。

这里发生了什么?一些神秘的优化?我忽略了一些明显的东西吗我正在使用支架编译器,版本1.8。我无法读取字节码,因此我不知道幕后发生了什么。

这是一个完整的测试类:https://gist.github.com/pbloem/1523283211454ec58ce9c5b45204eebd

字节码: https://gist.github.com/pbloem/ce4f6758f0bb1424c155c26e83ca88a1

2 个答案:

答案 0 :(得分:2)

可能JIT交换“if”的顺序以获得最佳性能,但不能将“else”(没有“if”)的顺序与开头的另一个“if”交换,所以当你在“if”之后添加“if”时“其他”,它尝试将其作为第一次检查,如果数组重叠与%90相同,那么它可以保留最后一个“如果”在第一位。

    if(a[i] == b[j])  // say %70 probability after N iterations
    {                 // or less randomized branching
        res ++;
        i ++;
        j ++;
    }
    else if(a[i] > b[j]) // %20 probability, medium branching
        j ++;
    else if(a[i] < b[j]) // %10, totally random branching, not predictable
        i ++;
当数组排序

时,

是可能的

  

a&gt; b或b&lt;

比数组重叠更随机。

如果有+ if + else,JIT可能无法预测你的意思。通过添加一个等式,除了等式之外,你正在消除许多情况。

你可以尝试使用有序数组和完全随机数组吗?

或者它只是帮助cpu的分支预测器,@ noahnu在评论中说。

答案 1 :(得分:-1)

通过使用System.currentTimeMillis(),您无法获得程序的确切耗用时间,因为有时由于JIT优化可能会出错。尝试使用System.nanoTime()

同时将时间计算中使用的变量作为适当微观基准的全局变量。

double sumWith = 0.0; double sumWithout = 0.0;