In the 2009 Google I/O talk about writing real-time games for Android http://developer.android.com/videos/index.html#v=U4Bk5rmIpic it is recommended that for performance we don't use interfaces. Supposedly the calls through an interface reference are about 30% slower. It is also mentioned that calls to static methods are faster.
In these circumstances, i asked myself if all calls to a non-direct reference are slower. I'm not an expert at low level stuff, but it looks to me that calling a method through a interface reference is about the same thing as calling a method through a reference to a parent class. But this would mean that we shouldn't use inheritance at all. And that, for someone like me that usually trades performance for scalability, it sounds crazy.
First I ran it on my PC and I was stupefied to find results like these at every run:
Direct refference => 1,596,318,257
Parent refference => 1,550,725,582
Interface refference => 1,552,626,591
Static refference => 1,751,394,872 So the interface calls are about the same. Actually sometimes they were faster by a negligible amount.
Then I tested it in an Android application, using a HTC Hero Phone. (Note: I reduced the number of iterations from 1000000000L to 5000000L).
Results were something like:
Direct refference => 3,767,791,749
Parent refference => 3,477,020,264
Interface refference => 4,690,185,547
Static refference => 3,327,636,719
So the interfaces are slower. I can now confirm with my own test. I guess the virtual machine is quite different.
The good thing is that calls through parent references are not slower. Wohoo! OOP for life
What do you guys think? I'm especially interested if the code I used is a good test case.
Also, I'm genuinely interested why interfaces are slower. I guess some king of lookup is done at runtime. But then why doesn't this happen for references to a parent class. In my example, the child class overrides the parent class so the same lookup should occur to tell the jvm to run the method in the child not the one in the parent.
Just curios ...could you re-do your test calling a final method (your implemented method is final ...or ..your implementig class is final). Basically I want to know if inlined methods changes something in your case.
Ya. I was thinking to do that myself. Here is the re-run:
On PC (sun-jdk):
Direct refference => 1,546,818,889
Direct refference (final method) => 1,544,656,939
Parent refference => 1,548,618,054
Interface refference => 1,552,144,756
Static refference => 1,737,086,755
On Android (1.5):
Direct refference => 3,650,238,037
Direct refference (final method) => 3,492,218,018
Parent refference => 3,484,863,281
Interface refference =3,869,232,177
Static refference => 3,345,306,297
I ran the test several times. I couldn't notice any real difference for final methods, though in theory there should be as final methods are not virtual.
Anyone around that can explain. Pretty please?!
Btw. I keep noticing that there is a small difference for static methods on PC. That makes it even more weird. Static methods should be faster right? The calls to static methods are resolved at compile time so no polymorphism lookup should occur.
Copied the test app. into Eclipse and ran it: Java 1.6.0_24, Windows XP Pro. Pentium E5200 at 3.1GHz. Bad move - weird results:
Slightly reduced performance could be accounted for by factors like running under Windows, network intrusions, age of this machine, but extended parent-reference speed does not compute. Now have compelling need to find out what is going on. To get a bit of a baseline converted app. to C++, code at http://pastebin.com/X8YzUS4a, compiled to native code.
Whee! Java is faster than C++ - mostly .
Still not happy, what happens if method modifies a field? Java: http://pastebin.com/jzjtScHq, C++: http://pastebin.com/SJwHc3YG. This arrangement gives a chance to compare calls with updating a field directly. Results in table: parent reference anomaly still there but nice to see that direct field-access gets little or no advantage. What Java needs now is properties to neaten up setter and getter code, preferably based on the original Delphi syntax with the single line option rather than the C# version .
Otherwise guess the next move is buy a JVM / Byte-code book. Can anyone recommend one?