以下是[Java performance]的一个例子:
public static void main(String[] args){
double d;
long start=System.currentTimeMillis();
for (int i=0;i<10;i++){
d=fblImpl1(50);
}
long end=System.currentTimeMillis();
System.out.println("elapsed time :"+(end-start));
}
private static double fblImpl1(int n){
if(n<0) throw new IllegalArgumentException("Must be >0");
if (n==0) return 0d;
if (n==1) return 1d;
double d =fblImpl1(n-2) +fblImpl1(n-1);
if (Double.isInfinite(d)) throw new ArithmeticException("overflow");
return d;
}
作者说现代JIT会像这样优化代码:
long start=System.currentTimeMillis();
long end=System.currentTimeMillis();
System.out.println("elapsed time :"+(end-start));
因为程序没有使用变量&#34; d&#34;在下面的。 但是在我的测试中,oracle hostspot jdk1.7没有做这个优化,程序需要运行很长时间才能完成。
@Holger,首先感谢您的回复。根据我的理解,我修改了以下代码:
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
doTest();
}
}
private static void doTest() {
double d;
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
d = fblImpl1(50);
}
long end = System.currentTimeMillis();
System.out.println("elapsed time :" + (end - start));
}
private static double fblImpl1(int n) {
//if (n < 0) throw new IllegalArgumentException("Must be >0");
if (n == 0) return 0d;
if (n == 1) return 1d;
double d = fblImpl1(n - 2) + fblImpl1(n - 1);
//if (Double.isInfinite(d)) throw new ArithmeticException("overflow");
return d;
}
} 但似乎JIT仍然没有按照我的预期应用任何优化。有什么不对吗?
答案 0 :(得分:1)
您不需要多次执行main方法,因为JIT可以编译经常执行的循环,因此不需要“doTest”。方法。似乎问题在于递归。如果用一些像sum这样的小事来替换fblImpl1,那么很容易得到想要的效果。
public static void main(String[] args) {
double d;
List<Long> list = new ArrayList<>();
for (int i = 0; i < 50000; i++) {
long start = System.nanoTime();
fblImpl1(20000);
long end = System.nanoTime();
list.add(end - start);
}
for(long z : list) {
System.out.println(z);
}
}
public static double fblImpl1(int n) {
int sum = 0;
for(int i = 0; i < n; i++) {
sum += i;
}
return sum;
}
以下代码生成如下结果:首先执行代码,然后获得零。 5812 5811 5812 5812 5812 5812 6088 6089 5812 6089 5812 5812 5811 5812 6089 6088 5812 .... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 277 0 0 0 0 0 0 0 0
我使用以下标志执行代码:
-XX:+PrintCompilation -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
提示:不要使用SystemCurrentTimeMillis,因为它的精度非常差(特别是在Windows上)