Search code examples
ccompiler-optimization

Does a function that only calls another function slow things down?


I saw some code that was something like this

int *func2(int *var) {
    //Do some actual work
    return var;
}

int *func1(int *var) {
    return func2(var);
}

int main() {
    int var;
    var = func1(&var);
    return 0;
}

This seems like an incredible waste to me but I figured the intermediate function might have previously had two function that it could call or there are some plans for expansion in the future. I was just wondering if compilers like gcc can detect this sort of thing and eliminate the useless function in the actual program or if this sort of thing actually wastes CPU cycles at runtime?


Solution

  • The super quick answer: Yes, maybe.

    The quick answer: Yes, but usually not enough that you should care, and sometimes not at all.

    The full answer: If the functions are all in the same translation unit and the compiler doesn't suck, the extra layer of function call will just get optimized out, and there will be zero impact on performance. Otherwise, if you're making external function calls, expect a small but nonzero performance cost. Most of the time it doesn't matter, but on functions that are super-short where every cycle counts, it could make your program twice as slow, or worse. Some worst-case examples:

    1. A function like getc that just pulls the next byte from a buffer, advances the position, and returns (in the common case where the buffer is non-empty).
    2. A function that advances a state machine via a trivial operation and returns, for example processing a single byte of a UTF-8 character.
    3. Locking/synchronization primitives. This is a bit of a special case because the actual atomic memory access should dominate the execution time, making overhead seem insignificant. But if your intended usage case is just to hold locks for a single trivial operation (e.g. lock(); a++; unlock();) then even a small amount of added time with the lock held could have drastic effects on contention performance if the lock is highly contended.

    Finally, the what-you-should-do answer: Write your code in the most natural way possible until testing/measurement shows you there's a performance problem. Only then should you think about uglifying your code for the sake of performance.