Alexander
Alexander

Reputation: 87

What is the actual time of execution of the method in Java and what does it depend?

I have one problem that I can't explain. Here is the code in main function:

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.");

If it is necessary: method Lehman.getFullFactorization(...) returns the ArrayList of prime divisors in String format.

Here is the output:

3151312423412354315

Lehman method: 
[5, 67, 24473, 384378815693]
0.149 sec.

Lehman method: 
[5, 67, 24473, 384378815693]
0.016 sec.

I was surprised, when I saw it. Why a second execution of the same method much faster than first? Firstly, I thought that at the first running of the method it calculates time with time of running JVM and its resources, but it's impossible, because obviously JVM starts before execution of the "main" method.

Upvotes: 0

Views: 145

Answers (5)

Peter Lawrey
Peter Lawrey

Reputation: 533442

Try doing it more than 10,000 times and it will be much faster. This is because the code first has to be loaded (expensive) then runs in interpreted mode (ok speed) and is finally compiled to native code (much faster)

Can you try this?

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.");

Upvotes: 1

f2lollpll
f2lollpll

Reputation: 1007

My guess is that it's saved in the L1/L2 cache on the CPU for optimization.

Or Java doesn't have to interpret it again and recalls it from the memory as already compiled code.

Upvotes: 0

Kru
Kru

Reputation: 4235

There are two things that make the second run faster.

  1. The first time, the class containing the method must be loaded. The second time, it is already in memory.
  2. Most importantly, the JIT optimizes code that is often executed: during the first call, the JVM starts by interpreting the byte code and then compiles it into machine code and continues the execution. The second time, the code is already compiled.

That's why micro-benchmarks in Java are often hard to validate.

Upvotes: 0

Andrey Atapin
Andrey Atapin

Reputation: 7935

I suppose the JVM has cached the results (may be particularly) of the first calculation and you observe the faster second calculation. JIT in action.

Upvotes: 0

joergl
joergl

Reputation: 2866

In some cases, Java's JIT compiler (see http://java.sun.com/developer/onlineTraining/Programming/JDCBook/perf2.html#jit) kicks in on the first execution of a method and performs optimizations of that methods code. That is supposed to make all subsequent executions faster. I think this might be what happens in your case.

Upvotes: 2

Related Questions