A query on a small benchmark test.

I ran a small code snippet from a book I am reading and was surprised by the results. The code calls an empty method and also a method with a variables assignment as the body. I figured the empty method call should have been quicker but it is consistently the other way round. Here is the code I ran:

class MethodBenchmarkextends Benchmark{

void benchmark(){

int x = 2+2+2+2+2+2+2;

}

//899543099 as above

//923825235 empty body

//925611216 empty body

//884589242 as above

publicstaticvoid main(String[] args){

int count = 100000000;

long time =new MethodBenchmark().repeat(count);

System.out.println(count +" methods in " +

time +" nanoseconds");

}

}

abstractclass Benchmark{

abstractvoid benchmark();

publicfinallong repeat(int count){

long start = System.nanoTime();

for (int i = 0; i < count; i++)

benchmark();

return (System.nanoTime() - start);

}

}

What is the reason for this?

By the way this is not a "Java is broke thread" I am sure there is a logical answer to this.

[2317 byte] By [_helloWorld_a] at [2007-11-27 6:11:38]
# 1
Not sure, but just so you know, it's not adding 2 + 2 + .... each time. That will get compiled to the constant 14 (if I counted right), so you're just doing x = 14. In addition, hotspot will probably optimize that away to a no-op anyway.
jverda at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 2

Yeah I guess I understood that, so the addition was pointless. I thought it might be to do with how constants are inserted separately into the bytecode for optimization but still it's extra data to consider at runtime and one would have thought it would be around the same or slightly more but is is always about 3000000-4000000 less which doesn't make sense at first glance.

_helloWorld_a at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 3
If benchMark() is polymorphic, the dispatch time may be a significant portion of the total time. Just make two methods in the same class as main, and for good measure, make them final.
jverda at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 4
Hotspot is a magical voodoo wonder. To me at least what this really demonstrates is why calling gc is almost always a bad idea. The VM knows what it's doing and will do a better job then you ever will of managing it's resources.
cotton.ma at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 5

I gave that a try and the time is a lot less but still with a difference, though not a noticeable still consistent, around 141000000 for empty and a low as 13950000 for an assignment.

I don't know why I am even bothering, it's not like I have any use for empty methods. I was just curious.

Cheers

_helloWorld_a at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 6
Another surprising one to me was once I tried comparing accessing a variable through a method vs direct access and the method was faster.Which I guess would have been one for the great encapsulation debate.
cotton.ma at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 7

I just came across this on Google.

http://java.sun.com/docs/hotspot/HotSpotFAQ.html#benchmarking_method

Here is an extract

Code is generated into memory and executed from there. The way the code is laid out in memory makes a big difference in the way it executes. In this example on my machine, the loop that claims to call the method is better aligned and so runs faster than the loop that's trying to figure out how long it takes to run an empty loop, so I get negative numbers for methodTime-loopTime.

Which would mean I was running the same code each time, the compiler would have ignored the body because it was dead and I was essential running an empty method body both times, but why the change?

But it also says this

The HotSpot compiler is smart enough not to generate code for dead variables.

In the method above, the local variable is never used, so there's no reason to compute its value. So then the method body is empty again and when the code gets compiled (and inlined, because we removed enough code to make it small enough for inlining) it turns into an empty method again.

I guess an inlined empty method in memory must be quicker than an empty method from the beginning.

Message was edited by:

_helloWorld_

_helloWorld_a at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...
# 8

> Another surprising one to me was once I tried

> comparing accessing a variable through a method vs

> direct access and the method was faster.

>

> Which I guess would have been one for the great

> encapsulation debate.

Yeah, I figured they would have been inlined to the same thing.

_helloWorld_a at 2007-7-12 17:18:01 > top of Java-index,Java Essentials,Java Programming...