Reputation: 133
I have two classes :
abstract class Employee{
protected int id;
public int getId(){
return id;
}
}
class Manager extends Employee{
}
In the course of the execution of the rest of my application I create lots of employee objects and call their getId() method many times.
The execution time is around 8 seconds. But if I add the following method to Manager :
@Override
public int getId(){
return super.id;
}
..the same program(keeping everything else constant) now runs in half as much time. I tested both versions multiple times and got the same results. Can anyone think of a reason for this?
Upvotes: 1
Views: 186
Reputation: 3679
Quite interesting,
To just confirm myself, I created test case, to replicate the behaviour, Given below the test case and test results
Case 1 when not overriding the method
Test Result
Run 1 - Creating 100000000 Employees Time taken to complete operation :501 (ms)
Run 2 - Creating 100000000 Employees Time taken to complete operation :507 (ms)
Run 3 - Creating 100000000 Employees Time taken to complete operation :502 (ms)
Case 2 -When overriding the method in sub class,
@Override
public int getId(){
return super.id;
}
Test Result
Run 1 - Creating 100000000 Employees Time taken to complete operation :486 (ms)
Run 2 - Creating 100000000 Employees Time taken to complete operation :497 (ms)
Run 3 - Creating 100000000 Employees Time taken to complete operation :478 (ms)
Case 3 - overriding the method, but not using super keyword
@Override
public int getId(){
return id;
}
Test Result
Run 1 - Creating 100000000 Employees Time taken to complete operation :457 (ms)
Run 2 - Creating 100000000 Employees Time taken to complete operation :471 (ms)
Run 3 - Creating 100000000 Employees Time taken to complete operation :471 (ms)
Observation:
There is minimal improvement when overriding the method/using directly(case 2 and case 3) ; but as best practise, most of the cases the variable would be declared private and method will be protected. If the variable itself protected, then you would need super key
---------- Full Test code for reference -----
public class TestEff {
public static void main(String[] args) {
System.out.println( " Creating 100000000 Employees ");
long st = System.currentTimeMillis();
for(int i=0;i<100000000;i++){
Manager mgr = new Manager();
int id =mgr.getId();
}
long et = System.currentTimeMillis();
long t = (et-st);
System.out.println(" Time taken to complete operation :"+t);
}
}
abstract class Employee{
protected int id;
public int getId(){
return id;
}
}
class Manager extends Employee{ @Override public int getId(){ return super.id; } }
Upvotes: 1
Reputation: 533492
When you run a micro-benchmark, you are very susceptible to how you have performed the benchmark and what code can be optimised away. This means that code which is basically the same can so subtle but relatively large differences in performance. However if you did the test a little differently or use a different update of Java you might find a very different result.
When you override a method in a sub-class you effectively make the class virtual. This means you can call Employee.getId()
or Manager.getId()
and it needs to check the type to determine which class method to call. The fact the methods are the same doesn't help. The JVM can be reasonably smart and inline the method, but since your method is trivial the very simple check of the type could means the difference in performance. .
It is also possible that this change turns of other optimisation. For example, an "infrequent" is only inlined if it is 35 bytes long. This can cause a problem with try/catch blocks. The try/catch block in itself doesn't slow down the code but can make the method bigger and mean it is no longer inlined. In your case, having a, overriden method can mean the calling code is a little bigger when your method is inlined and it is not optimised as aggressively.
Lastly I would check you code with the latest JVM. e.g. Java 7 update 40. You might find that this version doesn't show a difference in which case I would put it down to a bug in your version of the JVM.
Upvotes: 3