【发布时间】:2015-09-08 06:01:50
【问题描述】:
我今天阅读了Why is it faster to process a sorted array than an unsorted array? 的问题,并尝试在 Java 中复制结果。
这是我的代码:
public class BranchPredictorTest {
static int[] getBranchCounts1(List<Integer> list) {
long t0 = System.currentTimeMillis();
int[] counts = new int[3];
for(Integer v : list)
if(v < 1000)
counts[0]++;
else if(v < 2000)
counts[1]++;
else
counts[2]++;
System.out.println("[time cost]\t" + (System.currentTimeMillis() - t0) + " ms");
return counts;
}
static int[] getBranchCounts2(List<Integer> list) {
long t0 = System.currentTimeMillis();
int[] counts = new int[3];
for(Integer v : list)
counts[v/1000]++;
System.out.println("[time cost]\t" + (System.currentTimeMillis() - t0) + " ms");
return counts;
}
static void test(List<Integer> list) {
int[] bc1 = getBranchCounts1(list);
System.out.println(String.format("%d, %d, %d", bc1[0], bc1[1], bc1[2]));
int[] bc2 = getBranchCounts2(list);
System.out.println(String.format("%d, %d, %d", bc2[0], bc2[1], bc2[2]));
}
public static void main(String[] args) {
Random rand = new Random();
List<Integer> list = new ArrayList<Integer>();
for(int i=0; i<2e7; i++) {
list.add(rand.nextInt(3000));
}
test(list);
Collections.sort(list);
test(list);
}
}
您可以看到第一个功能是用分支实现的,而第二个功能是没有分支的。我为已排序和未排序的数组运行了这两个函数。根据我阅读的关于分支预测的内容,我预计时间成本为:
排序分支
但是结果有点奇怪:
[time cost] 145 ms
6670864, 6671007, 6658129
[time cost] 65 ms
6670864, 6671007, 6658129
[time cost] 332 ms
6670864, 6671007, 6658129
[time cost] 1852 ms
6670864, 6671007, 6658129
排序后的分支时间成本大于未排序的时间成本,并且arraylist排序后,un-branch计数的时间成本显着增加了它的运行时间......
编辑: 我在C++中尝试了同样的逻辑,结果基本符合预期:
[time cost] 248 ms
[time cost] 142 ms
[time cost] 87 ms
[time cost] 143 ms
我希望有人能给我解释一下这是怎么发生的,感谢您查看/回答我的问题。
【问题讨论】:
-
微基准测试很难。你用 JMH 试过了吗?