Yet another pamphlet about inlining

Introduction

This week’s topic will be about the inline keyword.

This is a very old subject that, for me, has been settled for years. And everytime I re-enter the subject and document myself about, I end up with the same conclusions.

However, I very often read code that misuse this keyword, ending up in counterproductive and risky situations.

I will try here to summarize all you need to remember about inlining, giving pros, cons and situations to use it and to not use it.

Definition

I’ll start with the academical definition of inline :

The original intent of the inline keyword was to serve as an indicator to the optimizer that inline substitution of a function is preferred over function call, that is, instead of executing the function call CPU instruction to transfer control to the function body, a copy of the function body is executed without generating the call. This avoids overhead created by the function call (passing the arguments and retrieving the result) but it may result in a larger executable as the code for the function has to be repeated multiple times.
Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.

Source : inline specifier – cppreference.com

What you need to retain from that are two things :

  • inline is used to avoid function overhead, replacing the call by the implementation at compile time.
  • It is only a hint given to the compiler. Some function declared inline may not really be inlined, and vice-versa.

With that in mind, let’s take a tour of the pros and the cons of this feature.

Pros

First of all, even if it’s a hint, the keyword may influence the compiler. It may not, but it also may. We can for instance think of the stupidest compiler that will just strictly respect the inline keyword, without trying to optimize himself. This is not against the standard (according to the C++11 standard §12.1.5) and the keyword is useful in this case.

According to What is C++ inline functions – C++ Articles (cplusplus.com), the pros are :

  1. It speeds up your program by avoiding function calling overhead.
  2. It save overhead of variables push/pop on the stack, when function calling happens.
  3. It save overhead of return call from a function.
  4. It increases locality of reference by utilizing instruction cache.
  5. By marking it as inline, you can put a function definition in a header file (i.e. it can be included in multiple compilation unit, without the linker complaining).

Point number 1, 2 and 3 are overally the main benefits of this feature, and the original goal of the introduction of this keyword. Those who know a bit of assembly know that pushing a lot of parameters on the stack to call function can cost more instructions that the function holds.

Point number 4 seems to be a non-negligible side-benefit of this method, but since instruction cache is far from being my specialty, I will nt develop on this.

Point number 5 is pro only in certain specific cases, but a pro nonetheless.

Cons

According to What is C++ inline functions – C++ Articles (cplusplus.com), the cons are :

  1. It increases the executable size due to code expansion.
  2. C++ inlining is resolved at compile time. Which means if you change the code of the inlined function, you would need to recompile all the code using it to make sure it will be updated
  3. When used in a header, it makes your header file larger with information which users don’t care.
  4. As mentioned above it increases the executable size, which may cause thrashing in memory. More number of page fault bringing down your program performance.
  5. Sometimes not useful for example in embedded system where large executable size is not preferred at all due to memory constraints.

Points 1 and 4, which are unknown to a lot of developpers, are the main reason that function inlining can decrease performance. It is important to remember that when using this feature.

Point 2 can be a major inconvenient, depending on your project, but don’t occur so often in my experience.

Point 3 is, in my opinion, the main con of this feature. In order to have maintainable code you need to have to be clear and organized. Inlining is a huge code smells in that regard.

Point 5 is about specific projects, so I will not develop further. But keep in mind that if you have memory constraints, inlining may have consequences.

Conlusion : when to use the inline keyword ?

Avoiding function overhead is only usefull if you are in a performance critical part of your code.

You probably already know the Pareto’s law : “80% of the execution happens in 20% of the code”. This means that the program spends most of it’s time in bottlenecks. Thus, if you inline code that is not within a bottleneck, this will have little to no effect on your program performance, while increasing its size.

What urged me to write this article is that during my coder’s life, I saw many many codebase polluted by useless inlines. I can safely say that more than 95% of the inlining I saw in industrial projects was used in non-critical code.

There is absolutly no need in decreasing the readability of the code and increasing the executable size for that end.

Here is my advice : don’t use inline unless you are 100% sure it is called inside a bottleneck.

This is the only way to be both efficient and clean.

Another type of inlining

I will end this article by adding a word about a special case of “inlining”.

If you are someone who likes to write things like this :

inline void setValue(int i) { m_value = i; }

and by that I mean, the prototype and the implementation all on one line, please understand that this prevent many debuggers from doing their jobs properly.

For instance, in VisualStudio, if you put a breakpoint inside this setValue method, when it hits the debugger won’t be able to give you the value of m_value.

So please, I’m begging you, stop doing that. It won’t cost you much to add a newline.

Thank you, and see you next week !

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s