我有一个我无法解释的问题。这是main函数中的代码:
String numberStr = "3151312423412354315";
System.out.println(numberStr + "\n");
System.out.println("Lehman method: ");
long beginTime = System.currentTimeMillis();
System.out.println(Lehman.getFullFactorization(numberStr));
long finishTime = System.currentTimeMillis();
System.out.println((finishTime-beginTime)/1000. + " sec.");
System.out.println();
System.out.println("Lehman method: ");
beginTime = System.currentTimeMillis();
System.out.println(Lehman.getFullFactorization(numberStr));
finishTime = System.currentTimeMillis();
System.out.println((finishTime-beginTime)/1000. + " sec.");
如果有必要:方法Lehman.getFullFactorization(...)
以字符串格式返回素数除数的ArrayList
。
这是输出:
3151312423412354315
Lehman method:
[5, 67, 24473, 384378815693]
0.149 sec.
Lehman method:
[5, 67, 24473, 384378815693]
0.016 sec.
当我看到它时,我感到很惊讶。为什么第二次执行同一方法比第一次快得多?首先,我认为在第一次运行该方法时,它会计算运行JVM及其资源的时间,但这是不可能的,因为显然JVM在执行“main”方法之前就已启动。
答案 0 :(得分:2)
在某些情况下,Java的JIT编译器(参见http://java.sun.com/developer/onlineTraining/Programming/JDCBook/perf2.html#jit)会在第一次执行方法时启动并执行该方法代码的优化。这应该会使所有后续执行更快。我想这可能就是你的情况。
答案 1 :(得分:1)
尝试超过10,000次,速度会快得多。这是因为代码首先必须加载(昂贵)然后以解释模式运行(ok速度)并最终编译为本机代码(更快)
你能试试吗?
int runs = 100*1000;
for(int i = -20000 /* warmup */; i < runs; i++) {
if(i == 0)
beginTime = System.nanoTime();
Lehman.getFullFactorization(numberStr);
}
finishTime = System.nanoTime();
System.out.println("Average time was " + (finishTime-beginTime)/1e9/runs. + " sec.");
答案 2 :(得分:0)
我认为JVM缓存了第一次计算的结果(可能特别),并且您观察到更快的第二次计算。 JIT在行动。
答案 3 :(得分:0)
有两件事使第二轮跑得更快。
这就是为什么Java中的微基准测试通常难以验证的原因。
答案 4 :(得分:0)
我的猜测是它保存在CPU的L1 / L2缓存中以进行优化。
或者Java不必再次解释它并从内存中将其作为已编译的代码重新调用。