10

This is general coding practice to use interface/base class reference when declaring an object like :

InterfaceIF ref = new SomeObject();

I understand that this provides loose coupling and we can change/write a new class with new implementation without affecting much code.

This is wonderfully explained here also.

But one thing which I am trying not able to understand, and is not answered on the question is :

  • Does performance gets effected by using interface/base class reference.
  • If, yes, then Is this affect positive or negative.
Community
  • 1
  • 1
codingenious
  • 8,385
  • 12
  • 60
  • 90
  • Nearly 99.999% certain, that performance does not get affected when using Interfaces. I wouldn't know how. Why do you think it would affect performance? – mwhs Nov 11 '13 at 09:58
  • @mwhs: It actually does. It could be a lot as the virtual call is pretty costly, but the JVM eliminates (nearly?) all of this overhead. – maaartinus Nov 11 '13 at 10:05
  • But if the JVM eliminates the overhead, then the costs would the same in the end wouldn't they? – mwhs Nov 11 '13 at 10:07
  • 1
    In any case, if there is a performance hit (which I doubt as I never seen a convincing proof that there is), then it is minimal, and it certainly doesn't outweigh the huge benefits in portability and scalability your program gains when programming against interfaces. Also it makes your code testable (dependency injection allows mocking or stubbing dependencies), which to me should be a reason enough to do that. – Guillaume Nov 11 '13 at 10:08
  • @Guillaume: I'm really NOT claiming you shouldn't do that. But you shouldn't doubt what's true. In the dark ages of Java, programmers were recommended to make their classes final for about this reason. Making [invokevirtual](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokevirtual) as fast as invokedynamic or invokestatic is a non-trivial achievement. – maaartinus Nov 11 '13 at 10:22

1 Answers1

9

Using the class directly may be faster, never slower. If the JVM sees a concrete class, it sort of knows "who to call". Not necessarily exactly as there may be subclasses, unless the class is final. There may be even subclasses not yet seen by the JVM which gets loaded later.

  • For a final class the method call can be optimized to the native CALL instruction. That's the trivial case.

  • If the class isn't final but there's no subclass loaded yet, it's the same with a single additional check somewhere at the beginning. When the check fails, the JVM must throw this over-optimistically compiled method away and recompile (no big deal).

  • When there are subclasses, then everything depends from how many of them were actually encountered on the given call site. If only one, then a fast check suffices to verify that the given class is the expected one (by moving this test out of loops etc., this overhead becomes negligible).

  • The cases with more candidates are obviously slower (Google for bimorphic and megamorphic).

Obviously, there's nothing what could make a call via an interface faster.

If there are multiple implementations and more than one gets called from a call site, then there's an overhead of the virtual call dispatch. For more details see this answer and this benchmark.

Community
  • 1
  • 1
maaartinus
  • 44,714
  • 32
  • 161
  • 320
  • 6
    *Using the class directly may be faster, never slower.* Can you explain this thesis? – mwhs Nov 11 '13 at 10:05
  • 1
    @mwhs: Enough explained? It's like calling somebody from your phonebook vs. calling the information service first. – maaartinus Nov 11 '13 at 10:25
  • 1
    @maaartinus Well. But will be cool if you post link to the proof. =) – Sergey Morozov Nov 11 '13 at 10:27
  • Interesting. Thanks for the detailed information. The overall effect seems to be nearly negligible, doesn't it? – mwhs Nov 11 '13 at 10:29
  • @frostjogla: Feel free to write a benchmark. Ignore all the warmup and other good recommendations and you can see the difference. After the JIT does it job well, you'll see the same timing, I guess. – maaartinus Nov 11 '13 at 10:35
  • @maaartinus Thanks. I am googled by "INVOKEVIRTUAL vs INVOKEINTERFACE": http://www.kaffe.org/pipermail/kaffe/1998-September/172057.html and https://www.usenix.org/legacy/events/coots01/dutchyn/dutchyn_html/index.html – Sergey Morozov Nov 11 '13 at 10:39
  • Thanks @maaartinus, this is a nice explanation and led me to read about stuff I'm not too familiar with - thanks for that! – Guillaume Nov 11 '13 at 10:57
  • @mwhs The difference between monomorphic, bimorphic and megamorphic [is huge, when the called method is simple](https://github.com/google/guava/issues/1268). The difference between calling via class or via interface may be similar, depending on additional details. Things are even more complicated than how I described them. – maaartinus Aug 16 '17 at 10:49