2

We're having a discussion with a friend concerning java code design and efficiency.

He argues methods should preferably be private for performance reasons as well as class consistency protection when overriding.

I argue methods should preferably be protected for complete customizability, and to avoid loosing time modifying and releasing an API as soon as its user want to change part of its behaviour.

We know the preference for composition over inheritance so here I mainly focus on performance comparison.

A simple test (see below) proves extended classes with parent having protected methods aren't slower than those with parent having private methods. It's even sometimes (I don't really understand performance change) faster.

elapsed:8051733.063 microseconds for A (private)
elapsed:8036953.805 microseconds for B (protected)

Do you think the below mentionned test is robust enough for making the comparison?

public class VerifPerfProtected {
public static void main(String[] args) {
    int ncalls = 1000000000; //10^9
    ChildrenClassA a = new ChildrenClassA();
    ChildrenClassB b = new ChildrenClassB();

    long start = System.nanoTime();
    a.manyCalls(ncalls);
    long stop = System.nanoTime();
    System.out.println("elapsed:" + (stop - start)/1000.0 + " microseconds for A (private)");

    start = System.nanoTime();
    b.manyCalls(ncalls);
    stop = System.nanoTime();
    System.out.println("elapsed:" + (stop - start)/1000.0 + " microseconds for B (protected)");
}

public static class ParentClassA{
    public void manyCalls(int n){
        for (int i = 0; i < n; i++) {
            callAmethod();
        }
    }
    public void callAmethod(){
        aPrivateMethod();
    }
    private void aPrivateMethod(){
        int a=0;
        for (int i = 0; i < 5; i++) {
            a++;
        }
    }
}

public static class ParentClassB{
    public void manyCalls(int n){
        for (int i = 0; i < n; i++) {
            callAmethod();
        }
    }
    public void callAmethod(){
        aProtectedMethod();
    }
    protected void aProtectedMethod(){
        int a=0;
        for (int i = 0; i < 5; i++) {
            a++;
        }
    }
}

public static class ChildrenClassA extends ParentClassA{        
}

public static class ChildrenClassB extends ParentClassB{        
}
}
Community
  • 1
  • 1
Martin Pernollet
  • 2,285
  • 1
  • 28
  • 39

4 Answers4

5

Do you think the below mentionned test is robust enough for making the comparison?

Frankly, no.

Micro-benchmarks are tricky; here is a good discussion regarding them. Personally, I always add warm-up time (e.g. the first x times I run a method are not counted for performance, giving various singletons a chance to initialize and giving the JIT compiler time to do its magic), and I make sure to run the JVM with the -server switch. Also, I suspect that the compiler might be smart enough to remove the a++ operations, since their result doesn't go anywhere.

But regardless of the correctness of your benchmark, I strongly believe that private vs. protected methods are a design issue, period. Possible performance difference between the two should have no effect whatsoever on the decision whether a method is made private or protected.

Community
  • 1
  • 1
Eli Acherkan
  • 6,401
  • 2
  • 27
  • 34
3

It is best not to confuse good design with performance requirements.

You should start with what is good design, and where you can't agree, you have to both accept it probably doesn't matter. Trying to use a performance comparison to find some measured way of choosing the difference is almost always a mistake because you don't know if the performance difference will matter anyway.

I suggest you allow for each developer to follow their own style unless there is a very good reason which can be agreed, not to do something.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

Private methods are non-virtual, so there is a tiny little fraction less overhead in calling them.

But you benchmark is flawed. From the back of an envelope, 1,000,000,000 calls in 8,000,000 microseconds. That's 8 ns for your method with a loop. HotSpot is reasonably capable of inlining virtual method calls. You code would be better with a warm up, repeat several times and look at the variation as well as the mean. Also, if you interleave algorithms, HotSpot may have to pessimise when you swap.

More importantly, protected is evil.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
1

I would prefer private methods for two reasons :

  • encapsulation : keep things as private as possible. Only make methods protected if they are really meant to be overriden. Makes refactoring and unit testing easier too, for you can rename/move around/split/etc. private methods with no risk of any side-effect anywhere else in your codebase.
  • optimization : private methods are easier for the JIT compiler to optimize (inline, etc.) because it knows it isn't overriden anywhere.
Olivier Croisier
  • 6,139
  • 25
  • 34