我正在使用以下简单代码进行一些性能测试(总计大约一百万个整数):
final int[] array = new int[1024 * 1024];
// populate values
for (int i = 0; i < array.length; i++) {
array[i] = i % 100;
}
long start, end, sum = 0;
start = System.nanoTime();
// calculate sum
for (int i : array) {
sum += i;
}
end = System.nanoTime() - start;
System.out.println(end);
平均执行时间约为 1.8ms 。
然后我决定改变测试结果的演示。我用以下语句(格式化字符串)替换System.out.println(end)
:
System.out.printf("Time in %dns, sum: %d\n", end, sum);
当我注意到我的平均执行时间大约是 2.8ms 时,这是非常令人惊讶的。它只有一毫秒(不是什么大不了的事),但另一方面它的强度大约是 50%。更重要的是,测试结果呈现(和格式化)位于结束时间测量之后,因此理论上不应影响平均执行时间。
您知道为什么在添加System.out.printf
语句后平均执行时间会花费更多时间吗?它是由重新排序(在为end
变量赋值之前执行格式化)引起的吗?
答案 0 :(得分:5)
我认为你无法从中得出任何结论。基本上,你的基准是有缺陷的:
在捕获测量值之前,预热 JVM没有采取必要的步骤。
可以优化您正在测量“工作”的循环。编译器(javac
或JIT编译器)可以推断出sum
从未使用过,因此不会计算它。
这些缺陷中的任何一个都可能会扭曲您所看到的结果。
对于它的价值,如果正确编写了基准,那么花哨的格式化根本不应该对测量的时间有所贡献。