Search code examples
javaandroidperformanceoverhead

Android: How much overhead is generated by running an empty method?


I have created a class to handle my debug outputs so that I don't need to strip out all my log outputs before release.

public class Debug {
    public static void debug( String module, String message) {
        if( Release.DEBUG )
            Log.d(module, message);
    }
}

After reading another question, I have learned that the contents of the if statement are not compiled if the constant Release.DEBUG is false.

What I want to know is how much overhead is generated by running this empty method? (Once the if clause is removed there is no code left in the method) Is it going to have any impact on my application? Obviously performance is a big issue when writing for mobile handsets =P

Thanks

Gary


Solution

  • Measurements done on Nexus S with Android 2.3.2:

    10^6 iterations of 1000 calls to an empty static void function: 21s  <==> 21ns/call
    10^6 iterations of 1000 calls to an empty non-static void function: 65s  <==> 65ns/call
    
    10^6 iterations of 500 calls to an empty static void function: 3.5s  <==> 7ns/call
    10^6 iterations of 500 calls to an empty non-static void function: 28s  <==> 56ns/call
    
    10^6 iterations of 100 calls to an empty static void function: 2.4s  <==> 24ns/call
    10^6 iterations of 100 calls to an empty non-static void function: 2.9s  <==> 29ns/call
    

    control:

    10^6 iterations of an empty loop: 41ms <==> 41ns/iteration
    10^7 iterations of an empty loop: 560ms <==> 56ns/iteration
    10^9 iterations of an empty loop: 9300ms <==> 9.3ns/iteration
    

    I've repeated the measurements several times. No significant deviations were found. You can see that the per-call cost can vary greatly depending on workload (possibly due to JIT compiling), but 3 conclusions can be drawn:

    1. dalvik/java sucks at optimizing dead code

    2. static function calls can be optimized much better than non-static (non-static functions are virtual and need to be looked up in a virtual table)

    3. the cost on nexus s is not greater than 70ns/call (thats ~70 cpu cycles) and is comparable with the cost of one empty for loop iteration (i.e. one increment and one condition check on a local variable)

    Observe that in your case the string argument will always be evaluated. If you do string concatenation, this will involve creating intermediate strings. This will be very costly and involve a lot of gc. For example executing a function:

    void empty(String string){
    }
    

    called with arguments such as

    empty("Hello " + 42 + " this is a string " + count );
    

    10^4 iterations of 100 such calls takes 10s. That is 10us/call, i.e. ~1000 times slower than just an empty call. It also produces huge amount of GC activity. The only way to avoid this is to manually inline the function, i.e. use the >>if<< statement instead of the debug function call. It's ugly but the only way to make it work.