4

http://s24.postimg.org/9y073weid/refactor_vs_non_refactor.png enter image description here Well here is the result for the execution time in nanoseconds for re-factored and non re-factored code for a simple addition operation. 1 to 5 are the consecutive runs of the code. My intent was just to find out whether splitting up logic into multiple methods makes execution slow or not and here is the result which shows that yes there is considerable time that goes into just putting the methods on stack.

I invite people who have done some research on it before or want to investigate on this area to correct me if I am doing something wrong and draw some conclusive results out of this. In my opinion yes code re-factoring does help in making code more structured and understandable but in time critical systems like real time game engines I would prefer not to re-factor.

Following was the simple code which I used:

    package com.sim;

public class NonThreadedMethodCallBenchMark{

public static void main(String args[]){
    NonThreadedMethodCallBenchMark testObject = new NonThreadedMethodCallBenchMark();
    System.out.println("************Starting***************");
    long startTime =System.nanoTime();

    for(int i=0;i<900000;i++){
        //testObject.method(1, 2); // Uncomment this line  and comment the line below to test refactor time
        //testObject.method5(1,2); // uncomment this line and comment the above line to test non refactor time
    }
    long endTime =System.nanoTime();
    System.out.println("Total :" +(endTime-startTime)+" nanoseconds");
}

public int method(int a , int b){
    return method1(a,b);
}
public int method1(int a, int b){
    return method2(a,b);
}
public int method2(int a, int b){
    return method3(a,b);
}
public int method3(int a, int b){
    return method4(a,b);
}
public int method4(int a, int b){
    return method5(a,b);
}
public int method5(int a, int b){
    return a+b;
}
public void run() {
    int x=method(1,2);
}

}

  • http://s24.postimg.org/9y073weid/refactor_vs_non_refactor.png this is the link for the graph – Kapil Kumar Gangwar Jun 23 '13 at 08:39
  • Instead of trying to conclude something from nonsense code like the one posted above, I would use a profiler to see where you are loosing most of the time in your real system. I will assure you, it is not calling of methods... – jlordo Jun 23 '13 at 08:39
  • 1
    Your benchmarking technique is deeply flawed and the results are probably meaningless. See, for example, [this thread](http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java). At a minimum, you should be using a microbenchmarking tool like [Caliper](https://code.google.com/p/caliper/). Also, measuring the performance of this code outside of any larger context is misguided. – Ted Hopp Jun 23 '13 at 08:48

2 Answers2

4

You should consider that code which doesn't do anything useful can be optimised away. If you are not careful you can be timing how long it takes to detect the code doesn't do anything useful, rather than run the code. If you use multiple methods, it can take longer to detect useless code and thus give different results. I would always look at the steady state performance after the code has warmed up.

For the most expensive parts of your code, small methods will be inlined so they won't make any difference to performance cost. What can happen is

  • smaller methods can be optimised better as complex methods can defeat optimisation tricks.
  • smaller methods can be eliminated as they are inlined.

If you don't ever warm up the code, it is likely to be slower. However, if code is called rarely, it is unlikely to matter (except in low latency system, in which case I suggest you warm up your code on startup)

If you run

System.out.println("************Starting***************");

for (int j = 0; j < 10; j++) {
    long startTime = System.nanoTime();
    for (int i = 0; i < 1000000; i++) {
        testObject.method(1, 2);
        //testObject.method5(1,2); // uncomment this line and comment the above line to test non refactor time
    }
    long endTime = System.nanoTime();
    System.out.println("Total :" + (endTime - startTime) + " nanoseconds");
}

prints

************Starting***************
Total :8644835 nanoseconds
Total :3363047 nanoseconds
Total :52 nanoseconds
Total :30 nanoseconds
Total :30 nanoseconds

Note: the 30 nano-seconds is the time it takes to perform a System.nanoTime() call. The inner loop and the methods calls have been eliminated.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

Yes, extra method calls cost extra time (except in the circumstance where the compiler/jitter actually does inlining, which I think some of them will do sometimes but under circumstances that you will find hard to control).

You shouldn't worry about this except for the most expensive part of your code, because you won't be able to see the difference in most cases. In those cases where performance doesn't matter, you should refactor to maximize code clarity.

I suggest you refactor at will, occasionally measure performance using a profiler to find the expensive parts. Only when the profiler shows that some specific code is using a significant fraction of the time, should you worry about about function calls (or other speed vs. clarity tradeoffs) in that specific code. You will discover that the performance bottlenecks are often in places that you wouldn't have guessed.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • The code is is eliminated in both cases so take no time at all. The extra time is how much longer it takes the JIT to eliminate the code. i.e. the OP is not testing what he/she thinks they are testing. – Peter Lawrey Jun 23 '13 at 10:14
  • @PeterLawrey: uh, *which* code is eliminated? You mean both cases in the OP's example? Yes, that would mean he learns that calls sometimes get eliminated if he measu=es well, so that's actually useful. But what matters is his code, not this example. – Ira Baxter Jun 23 '13 at 14:40
  • In that case, the answer depends on what his real code looks like and how he tests it. – Peter Lawrey Jun 24 '13 at 07:00