Sta*_*bbz 86 java methods performance static object
在此代码中,当我在main
方法中创建一个Object 然后调用该对象方法:( ff.twentyDivCount(i)
运行在16010毫秒)时,它运行速度比使用此注释调用它快得多:( twentyDivCount(i)
运行在59516毫秒).当然,当我在不创建对象的情况下运行它时,我将方法设为静态,因此可以在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");
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:到目前为止,似乎不同的机器产生不同的结果,但使用JRE 1.8.*是原始结果似乎一致再现的地方.
ass*_*ias 72
使用JRE 1.8.0_45我得到了类似的结果.
调查:
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
VM选项运行java 显示两个方法都被编译和内联main
就会大不相同,实例方法会得到更积极的优化,特别是在循环展开方面然后我再次运行你的测试,但是使用不同的循环展开设置来确认上面的怀疑.我运行你的代码:
-XX:LoopUnrollLimit=0
并且两种方法都运行缓慢(类似于使用默认选项的静态方法).-XX:LoopUnrollLimit=100
并且两种方法都运行得很快(类似于带有默认选项的实例方法).作为结论,似乎使用默认设置,当方法是静态时,热点1.8.0_45的JIT 无法展开循环(尽管我不确定它为什么会这样).其他JVM可能会产生不同的结果.
maa*_*nus 33
只是一个未经证实的猜测基于assylias的答案.
JVM使用一个阈值进行循环展开,这类似于70.无论出于何种原因,静态调用稍微大一点并且不会展开.
LoopUnrollLimit
52以下,两个版本都很慢.这很奇怪,因为我的猜测是静态调用在内部表示中略大,而OP遇到了一个奇怪的情况.但差异似乎大约是20,这没有任何意义.
-XX:LoopUnrollLimit=51
5400 ms NON_STATIC
5310 ms STATIC
-XX:LoopUnrollLimit=52
1456 ms NON_STATIC
5305 ms STATIC
-XX:LoopUnrollLimit=71
1459 ms NON_STATIC
5309 ms STATIC
-XX:LoopUnrollLimit=72
1457 ms NON_STATIC
1488 ms STATIC
Run Code Online (Sandbox Code Playgroud)
对于那些愿意尝试的人来说,我的版本可能很有用.
归档时间: |
|
查看次数: |
8254 次 |
最近记录: |