好吧所以我正在Eclipse Neon上玩游戏,我注意到当我向程序添加一个break语句时,它显着减慢了程序速度从大约120 fps到80 fps(这没什么意义)。所以我决定在另一个班级测试它并得到类似的结果。
这是我运行的代码:
public static int[] xArray = new int[100000];
public static int[] yArray = new int[10000];
public static void main(String[] args){
long timeStart = System.currentTimeMillis();
int numberOfLoops = 0;
int uboveMax = 0;
for(int x = 0; x < xArray.length; x++){
for(int y = 0; y < yArray.length; y++){
numberOfLoops++;
if(y > 9000){
uboveMax++;
//break;
}
}
}
long timeTaken = System.currentTimeMillis();
System.out.println("Number of Loops: " + numberOfLoops);
System.out.println("Ubove Max: " + uboveMax);
System.out.println("Time Taken(MS): " + (timeTaken - timeStart));
}
所以当我运行代码时(在Eclipse Neon 2(4.6.2)中)我得到了意想不到的结果:
使用break语句: 拍摄时间(MS): 344.8 (5次测试的平均值)
没有休息声明: 拍摄时间(MS): 294.6 (5次测试的平均值)
然后,当我运行代码时(在NetBeans IDE 8.2中),我得到了预期的结果:
使用break语句: 拍摄时间(MS): 4.2 (5次测试的平均值)
没有break语句: 拍摄时间(MS): 556.8 (5次测试的平均值)
使用break语句的代码(在Eclipse中)是否应该以更快的速度运行至少相同的速度?另外,Eclipse和NetBeans之间存在巨大差异的原因是什么,我知道它们是非常不同的程序,但是不同时运行来自同一JVM的代码,它们是否与Eclipse编译器有关?如果有人能为这一事件提供一个很好的解释,谢谢!
答案 0 :(得分:2)
这最好是一个评论,但它太长了。您的代码的问题在于它所做的相当于
System.out.println("Number of Loops: " + 1000000000);
System.out.println("Ubove Max: " + 99900000);
这可以优化到几个周期。这不会发生,因为您没有给JVM足够的时间和/或因为OSR(请参阅此question以获得一个很好的示例)。
您的代码(不含break
)可以优化为
for(int x = 0; x < xArray.length; x++) {
numberOfLoops += yArray.length;
uboveMax += Math.max(0, yArray.length - 9001);
}
进一步
numberOfLoops += xArray.length * yArray.length;
uboveMax += xArray.length * Math.max(0, yArray.length - 9001);
使用break
的代码会导致类似的表达。如果我是JVM,我会因为你在这种无意义上浪费时间而感到沮丧。 JVM并不沮丧,如果你给了它一个机会,你会发现在两种情况下接近于零的时间。这是可能但不可能的,即(即使有足够的时间)其中一个案例没有得到优化和其他案例,但这不是必不可少的,只是有无数的优化可能性,并且有些情况下JVM错过了某些东西
恕我直言,这个例子不会让你深入了解为什么你的实际代码会发生减速。为了找到问题而简化代码是好的,但你走得太远了。实际上,您的变量会做一些事情,并可能影响未来的计算方式,以便突破循环案例,将来还有更多工作要做。只是猜测,但没有真正的代码还有什么呢?