【发布时间】:2013-09-27 20:53:06
【问题描述】:
我写了下面的Java测试
public class NegativeTest {
/**
* @param args
*/
public static void main(String[] args) {
long start = System.currentTimeMillis();
int value = 12345;
for (int j = 0; j < 30; j++) {
for (int i = 0; i < 1000000000; i++) {
value = value * -1 - i;
}
}
System.out.println(System.currentTimeMillis() - start);
//to avoid compilation optimization
System.out.println(value);
}
}
在我的 Intel(R) Core(TM) i5-3210M (Ivy-Bridge) 机器上完成大约需要 1.3 秒,但是在我更改线路之后
值 = 值 * -1 - i
到
价值=价值-我,
然后大约需要 10 秒 才能完成(大约是之前版本的 10 倍)!
当我在其他非 Sandy Bridge CPU 上运行此测试时,结果完全相反: value = value * -1 - i 版本花费的时间是 value = value - i 版本的两倍!
谁能解释这个区别?是否与 Sandy Bridge 架构中的任何特定优化设计有关??
【问题讨论】:
-
这很有趣。当我在 C++ 中尝试此操作时,第一种情况为 0 秒,第二种情况为 7.472 秒。似乎在第一种情况下,我的 C++ 编译器设法将循环完全优化为单个值。所以这基本上归结为编译器优化。也许 Java JIT 正在为 SB 做一些不同的事情。 (哦,我在 Sandy Bridge 机器上测试过)
-
@Mysticial 你在非沙桥机器上试过了吗?
-
没关系。因为我的 C++ 编译器将第一种情况优化为基本上
print("-2115085767")。这将在任何处理器上以零时间运行。 -
为了确定问题在于 CPU 的存在与否,您必须确保系统的其他软件组件相同。例如,两台机器是否具有:相同的 jdk 版本和位深度(32/64)?相同的 JVM 版本和位深度?同一个操作系统? Java 编译器和 JVM 都可以在系统为解决此问题而采取的确切路径中发挥作用。正如我们所见,某个 C++ 编译器实际上解决了这个问题,只是输出了一个打印答案的程序!
-
如果我有一个
long value而不是int value,那么时间几乎是一样的。我怀疑区别在于 JIT 可以优化多少代码。
标签: java performance cpu