3

I am from Python and still new at c++. Now I wonder if calling a function is slower in performance then calling the code of the func itself?

Some example.

struct mynum {
public:
     int m_value = 0;
     constexpr 
     int value() { return m_value; }

     // Say we would create a func here.
     // That wants to use the value of "m_value"
     // Is it slower to use "value()" instead of "m_value"?
     // Even if the difference is very small.
     // Or is there indeed no difference because everything gets compiled.
     void somefunc() {
         if(value() == 0) {}
     }

}
  • 1
    You should not worry about such matters. Write for correctness and clarity first. – Passer By Jul 31 '22 at 06:57
  • 1
    There is a cost to calling a function. However, you can declare the function `inline`, in which case the compiler will move the code inline, and avoid the function call. There are overviews on [cplusplus.com](https://cplusplus.com/articles/2LywvCM9/), [cpppreference](https://en.cppreference.com/w/cpp/language/inline), and [Microsoft's documentation site](https://docs.microsoft.com/en-us/cpp/cpp/inline-functions-cpp?view=msvc-170). This gives you the benefit of performance while retaining code cleanliness. Old compilers may not respect `inline`, others may inline simple stuff without it. – Perette Jul 31 '22 at 06:58
  • 2
    @perette No, `inline` has nothing to do with inlining, and cplusplus.com is a terrible site. – Passer By Jul 31 '22 at 06:58
  • 1
    C++ Compilers will optimize the value() by inilining it. So in debug mode calling value() is a bit less efficient but in relaese mode they will be same unless you disable the optimization in release mode too. – Dariush Eivazi Jul 31 '22 at 06:59

2 Answers2

1

If the function body is available at the time it is called, there is a good chance the compiler will try to either automatically inline it (the "inline" keyword is just a hint) or leave it as a function body. In both cases you are probably in the best path as compilers are pretty good at this kind of decisions - or better than us.

If only the function prototype (the declaration) is known by the compiler and the body is defined in another compilation unit (*.cpp file) then there are a couple of hits you might take:

  1. The processor pipeline (and speculative execution) might stall which may call you a few cycles although processors have become extremely efficient at these things in the past 10 years or so. Even dynamic branch optimization has become so good that there is no point rearranging the order or if/else like we used to do 20 years ago (still necessary for microprocessors though).

  2. The register optimization will display a clean cut, which will affect some intensive calculations primarily. Basically the processor runs an optimization to decide in which registers the variables being used will reside on. When you make a call, only a couple of them will be guaranteed to be preserved, all the others will need to be reloaded when the function returns. If the number of variables active is large, that load/unload can affect performance but that is really rare.

  3. If the function is a virtual method, the indirect lookup on the virtual table might add up to ten cycles. Compilers might de-virtualize a call if it knows exactly which class will be called however so this cost might be actually the same of a normal function. In more complex cases, with several layers of polymorphism then virtual calls might take up to 20 cycles. On my tests with 2 layers the cost is in average 5-7 cycles on an AMD Zen3 (Threadripper).

But overall if the function call is not virtual, the cost will be really negligible. There are programmers that swear by inlining everything but if my experience is worth note, I have programatically generated code 100% inlined and the same code compiled in separate and the performance was largely the same.

Something Something
  • 3,999
  • 1
  • 6
  • 21
0

There is some function call overhead in C++, but a simple function like this that just returns a known variable will probably be compiled out and replaced with a reference to that variable.

scatter
  • 903
  • 7
  • 24