等效静态和非静态方法的速度差异很大 [英] Large difference in speed of equivalent static and non static methods
问题描述
在此代码中,当我在 main
方法中创建一个Object,然后调用该对象方法时: ff.twentyDivCount(i)
(运行时间为16010毫秒),运行速度比使用此注释调用它要快得多: twentyDivCount(i)
(运行时间为59516毫秒)。当然,当我在不创建对象的情况下运行它时,我将方法设为静态,因此可以在main中调用它。
In this code when I create an Object in the main
method and then call that objects method: ff.twentyDivCount(i)
(runs in 16010 ms) , it runs much faster than calling it using this annotation: twentyDivCount(i)
(runs in 59516 ms). Of course, when I run it without creating an object, I make the method static, so it can be called in the main.
public class ProblemFive {
// Counts the number of numbers that the entry is evenly divisible by, as max is 20
int twentyDivCount(int a) { // Change to static int.... when using it directly
int count = 0;
for (int i = 1; i<21; i++) {
if (a % i == 0) {
count++;
}
}
return count;
}
public static void main(String[] args) {
long startT = System.currentTimeMillis();;
int start = 500000000;
int result = start;
ProblemFive ff = new ProblemFive();
for (int i = start; i > 0; i--) {
int temp = ff.twentyDivCount(i); // Faster way
// twentyDivCount(i) - slower
if (temp == 20) {
result = i;
System.out.println(result);
}
}
System.out.println(result);
long end = System.currentTimeMillis();;
System.out.println((end - startT) + " ms");
}
}
编辑:到目前为止,似乎不同的机器产生不同的结果,但使用JRE 1.8。*是原始结果似乎一致再现的地方。
So far it seems that different machines produce different results, but using JRE 1.8.* is where the original result seems to be consistently reproduced.
推荐答案
使用JRE 1.8.0_45我得到类似的结果。
Using JRE 1.8.0_45 I get similar results.
调查:
- 使用<$ c运行java $ c> -XX:+ UnlockDiagnosticVMOptions -XX:+ PrintCompilation -XX:+ PrintInlining VM选项显示两种方法都被编译和内联
- 查看生成的方法本身的程序集本身没有显着差异
- 然而,一旦它们被内联,
main
中生成的程序集就会大不相同了,实例方法被更积极地优化,特别是在循环展开方面
- running java with the
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
VM options shows that both methods get compiled and inlined - Looking at the generated assembly for the methods themselves shows no significant difference
- Once they get inlined, however, the generated assembly within
main
is very different, with the instance method being more aggressively optimised, especially in terms of loop unrolling
然后我再次运行你的测试,但是使用不同的循环展开设置确认上面的怀疑。我用以下代码运行你的代码:
I then ran your test again but with different loop unrolling settings to confirm the suspicion above. I ran your code with:
-
-XX:LoopUnrollLimit = 0
以及两种方法运行缓慢(类似于使用默认选项的静态方法)。 -
-XX:LoopUnrollLimit = 100
并且两种方法都运行得很快(类似于带有默认选项的实例方法)。
-XX:LoopUnrollLimit=0
and both methods run slowly (similar to the static method with the default options).-XX:LoopUnrollLimit=100
and both methods run fast (similar to the instance method with the default options).
结论看来,使用默认设置,JIT 的>无法展开循环(虽然我不确定它为什么会这样)。其他JVM可能会产生不同的结果。
As a conclusion it seems that, with the default settings, the JIT of hotspot 1.8.0_45 is not able to unroll the loop when the method is static (although I'm not sure why it behaves that way). Other JVMs may yield different results.
这篇关于等效静态和非静态方法的速度差异很大的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!