Home > Software engineering >  C call member method vs normal function overhead
C call member method vs normal function overhead

Time:06-10

Suppose whatever C class that performs an operation like this:

void MyClass::operation()
{
    // final sum it's just a class member
    finalSum = {0};

    for (int i = 0; i < 100; i  )
        if (i % 2 = 0)
            finalSum  = 2;
        else
            finalSum  = 1;
}

Instead of write a bunch of operations inside just one method, you refactor part of that calculations to a new method, so code now looks like this:

void MyClass::operation()
{
    // finalSum it's just a class member
    finalSum = {0};

    for (int i = 0; i < 100; i  )
        calculateIncrement(i);
}

MyClass::calculateIncrement(int i)
{
    if (i % 2 = 0)
        finalSum  = 2;
    else
        finalSum  = 1;
}

So, two questions:

  • There's a little bit of overhead for make that method call? It's really relevant?
  • It's cheaper (in terms of memory and CPU usage) to call a method of an instance that calling an external function (any non-member fn that performns the same operation than calculateIncrement(), but with a return value?
  • What if you pass the instance of your object by non-const reference or pointer to that external function? It's the overhead the same?

Code it's minimal, but you can argue with more complicated values that the language primitives, and suppose larger and complicated calculations than the proposed above.

Thanks.

CodePudding user response:

Don't do premature optimization. Correctness is much more important than performance. The fastest code is worth nothing when it does not compile or produce wrong output.

Write code to be readable. Readable code is easier to test, debug and to refactor. Once you have working correct code you can measure to see where are the bottlenecks.

Anyhow, compilers are smart enough to see the pattern of loops similar to this one:

 int sum = 0;
 for (int i=0; i < 100;   i) sum  = i;

Knowing this, I changed your calculations to this (without this transformation I didn't get the desired output):

int main() {
        // final sum it's just a class member
    int finalSum = {0};

    for (int i = 0; i < 100; i =2)
            finalSum  = 2;
    for (int i = 1; i < 100; i =2) 
            finalSum  = 1;
    return finalSum;
}

Turned on optimizations (-O3) to get as a result:

main:
        mov     eax, 150
        ret

There is no need to write a loop and no need to call a function. Even though I did write two loops in the code, the compiler was smart enough to see that the final result can be determined at compile time. This is the kind of optimizations that make C code run fast. Human-driven optimizations must always be based on profiling and measurements, and it is really hard to beat a good compiler. Though in this case you could have noticed that the final result is just 150 and that there is no need for the loop.

Conclusion: Write code to be simple and readable. The code you posted effectively assigns 150 to finalSum and the most simple way to express this is finalSum = 150;.

You may argue that I missed the point of the question. But my point is that details matter. Different code will have different opportunities to make it simpler and more expressive. It is difficult/impossible to make a general statement about whether a function call introduces too much overhead. Anyhow the compiler is much better at making this decision. It may inline the call or not when it sees that it will be worth it.

  • Related