4

I wonder if performances of an application could be improved by using the more superclasses you can. My question is about Kotlin, but I assume the answer will be the same for Java.


Let's say you have this inheritance schema (the right class is a subclass of the class on his left):
A < B < C < D < E < F < G < ... And so on until Z.

Saying you don't need all the stuff defined in all the subclasses, but only the attributes and the functions of the A class. For an obscure reason, your code uses only Z class.

My question is quite simple: If you change your code to only use A class instead of Z class, will the code be more performant?

Thank you in advance for your answers.

Ctorres
  • 468
  • 6
  • 19
  • 1
    If you're thinking about the cost of method calls, those are not affected by the depth of the type hierarchy. There's a small overhead for having inheritance in the first place (compared to, e.g., static methods), but even that can be jitted away. – OhleC Jan 25 '19 at 09:52
  • @Hulk I ask about both. My question comes from the fact I'm currently using the interface "JpaRepository" which is a subclass of "CrudRepository" in Spring Data JPA, and for now, I don't need the stuff defined in "JpaRepository", then I wonder if I should switch to "CrudRepository". More details in this question: https://stackoverflow.com/questions/14014086/what-is-difference-between-crudrepository-and-jparepository-interfaces-in-spring – Ctorres Jan 25 '19 at 09:58
  • Thank you for your answer, but I'm looking for a general answer, I assume using "JpaRepository" instead of "CrudRepository" will never affect the performances of my code enough to see the diffrerence, but I wonder if this could be the case on a huge application with many classes, and a lot of inheritance... My question is purely theorical, and I don't think the answer will change my coding habits, but I really want to know... – Ctorres Jan 25 '19 at 10:15
  • 1
    I do not think this is a real time scenario. In real cases you should not need more depth of 3-4 I think. Even if this was your case, I do not think that is easy to manage, and pretty hard to maintain in this scenario. – Akiner Alkan Jan 25 '19 at 10:15
  • @Hulk So we can say that creating instances of A instead of Z will be more efficient because A class contains less attributes and methods than Z. That is the answer I was looking for, even if it's perfectly logical, and pretty obvious now you said it. If you take time to redact an answer, I will accept it. Thank you. – Ctorres Jan 25 '19 at 10:35
  • The question isn't clear whether it's asking about changing the types of *object* used, or the types of *reference* used to access them.  Since `JpaRepository` and `CrudRepository` are *interfaces*, I guess it must be asking about reference types.  (In which case the answer is: no, I think it doesn't matter in the slightest, because the dispatch is done on the object itself, not the reference type.) – gidds Jan 25 '19 at 12:50
  • @gidds Sorry if my question wasn't clear. It wasn't about interfaces, I just meant that choosing one of those interfaces made me wonder this question. That's all. But I'm talking about concrete classes in my questions. – Ctorres Jan 25 '19 at 13:36
  • That's all a bit difficult. I think it depends on 1. whether there are method calls involved that *might* be overridden at each inheritance level, and 2. whether there are *multiple* implementations of the same method. See things like https://www.javaspecialists.eu/archive/Issue157.html , or more recently and more technically, https://shipilev.net/jvm-anatomy-park/16-megamorphic-virtual-calls/ – Marco13 Jan 26 '19 at 01:53

2 Answers2

3

If

"change your code to only use A class instead of Z class"

includes construction, then there is a trivial answer:

Creating and storing an object with less attributes/fields is cheaper than creating an object with more attributes, both in terms of memory and in terms of time it takes to initialize.

Other than that, I would not expect a significant effect on performance.


That said, I wouldn't worry about performance here - choose the type that provides the best abstraction for what you want to do with this. If your code doesn't care what specific subclass you are using and doesn't need any of the functionality provided by the subclasses, use the more general type. That way your code remains more flexible. If your code however needs such functionality at some point, i.e. you have to introduce casts further down the line, then you have gone too far.

Hulk
  • 6,399
  • 1
  • 30
  • 52
1

The answer is yes. For example, if you invoke the method z.someMethod(). The Hotspot will look up the method in Z class first. If HotSpot does not found the target method, it will look up the method in Z's parent. And continue these steps until it found the target method. So it will take more time to lookup the method if the inheritance chain is long.

However, HotSpot using some cache to accelerate the process.

HotSpot VirtualCalls

flycash
  • 414
  • 4
  • 8
  • 1
    This lookup is done once when a class is being loaded. It is too trivial to be considered an overhead. – jingx Jan 25 '19 at 16:47
  • You are right. After class loading and linking, HotSpot knows the target method's vtable slot. Calling a virtual method, it just index an array, like vtable[slot]... – flycash Jan 26 '19 at 01:37