When to use inline function and when not to use it?

117,359

Solution 1

Avoiding the cost of a function call is only half the story.

do:

  • use inline instead of #define
  • very small functions are good candidates for inline: faster code and smaller executables (more chances to stay in the code cache)
  • the function is small and called very often

don't:

  • large functions: leads to larger executables, which significantly impairs performance regardless of the faster execution that results from the calling overhead
  • inline functions that are I/O bound
  • the function is seldom used
  • constructors and destructors: even when empty, the compiler generates code for them
  • breaking binary compatibility when developing libraries:
    • inline an existing function
    • change an inline function or make an inline function non-inline: prior version of the library call the old implementation

when developing a library, in order to make a class extensible in the future you should:

  • add non-inline virtual destructor even if the body is empty
  • make all constructors non-inline
  • write non-inline implementations of the copy constructor and assignment operator unless the class cannot be copied by value

Remember that the inline keyword is a hint to the compiler: the compiler may decide not to inline a function and it can decide to inline functions that were not marked inline in the first place. I generally avoid marking function inline (apart maybe when writing very very small functions).

About performance, the wise approach is (as always) to profile the application, then eventually inline a set of functions representing a bottleneck.

References:


EDIT: Bjarne Stroustrup, The C++ Programming Language:

A function can be defined to be inline. For example:

inline int fac(int n)
{
  return (n < 2) ? 1 : n * fac(n-1);
}

The inline specifier is a hint to the compiler that it should attempt to generate code for a call of fac() inline rather than laying down the code for the function once and then calling through the usual function call mechanism. A clever compiler can generate the constant 720 for a call fac(6). The possibility of mutually recursive inline functions, inline functions that recurse or not depending on input, etc., makes it impossible to guarantee that every call of an inline function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate 720, another 6 * fac(5), and yet another an un-inlined call fac(6).

To make inlining possible in the absence of unusually clever compilation and linking facilities, the definition–and not just the declaration–of an inline function must be in scope (§9.2). An inline especifier does not affect the semantics of a function. In particular, an inline function still has a unique address and so has static variables (§7.1.2) of an inline function.

EDIT2: ISO-IEC 14882-1998, 7.1.2 Function specifiers

A function declaration (8.3.5, 9.3, 11.4) with an inline specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.

Solution 2

inline has very little to do with optimization. inline is an instruction to the compiler not to produce an error if the function given definition occurs multiple times in the program and a promise that the definition will occur in every translation that it is used and everywhere it does appear it will have exactly the same definition.

Given the above rules, inline is suitable for short functions whose body doesn't necessitate including extra dependencies over what just a declaration would need. Every time the defintion is encountered it must be parsed and code for its body may be generated so it implies some compiler overhead over a function defined only once in a single source file.

A compiler may inline (i.e. replace a call to the function with code that performs that action of that function) any function call that it chooses. It used to be the case that it "obviously" couldn't inline a function that wasn't declared in the same translation unit as the call but with the increasing use of link time optimization even this isn't true now. Equally true is the fact that functions marked inline may not be inlined.

Solution 3

Telling the compiler to inline a function is an optimization, and the most important rule of optimization is that premature optimization is the root of all evil. Always write clear code (using efficient algorithms), then profile your program and only optimize functions that are taking too long.

If you find a particular function is very short and simple, and it's getting called tens of thousands of times in a tight inner loop, it might be a good candidate.

You might be surprised, though - many C++ compilers will automatically inline small functions for you - and they might ignore your request to inline, too.

Solution 4

Premature optimization is the root of all evil!

As a rule of thumb I usually inline only "getters" and "setters". Once the code is working and is stable, profiling can show which functions could benefit from inlining.

On the other hand, most modern compilers have quite good optimization algorithms, and will inline what you should have inlined for you.

Reasuming -- write inline one-liner functions, and worry about others later.

Solution 5

The best way to find out is to profile your program and mark small functions that get called lots of times and burn through CPU cycles that as inline. The keyword here is "small" - once the function call overhead is negligible compared to the time spent in the function, it's pointless to inline them.

The other use I'd suggest is if you've got small functions that get called in performance critical code often enough to make a cache miss relevant, you should probably inline those as well. Again, it's something the profiler should be able to tell you.

Share:
117,359

Related videos on Youtube

Ashish
Author by

Ashish

I am very zealous and innovative person. I like exploring how things work internally and getting a thorough knowledge of it. I also read technical books in my spare time.

Updated on July 03, 2020

Comments

  • Ashish
    Ashish almost 4 years

    I know that inline is a hint or request to compiler and its used to avoid function call overheads.

    So on what basis one can determine whether a function is a candidate for inlining or not ? In which case one should avoid inlining ?

    • Gregory Pakosz
      Gregory Pakosz over 14 years
      inline is to the C++ newcomer what CFLAGS are to the Gentoo newcomer: no, compiling with -O3 -funroll-loops -finline-functions won't make your old Pentium fly ;)
    • Rob deFriesse
      Rob deFriesse over 14 years
      A reason not to use inline is that some debuggers won't allow you to set a break point or step into an inlined function.
    • Steve Jessop
      Steve Jessop over 14 years
    • David Thornley
      David Thornley over 14 years
      You shouldn't determine whether a function should be inlined or not. Let the compiler do it; it's better at it than you are (and can inline functions selectively based on the environment of each call).
    • talekeDskobeDa
      talekeDskobeDa over 4 years
      @DavidThornley Sometimes, even with O3 flag set, the compiler does not inline the function if the definition is in cpp file. So, the thumb rule that I follow is to inline one liners and also those functions without any loops.
    • Volper
      Volper over 3 years
      @talekeDskobeDa you can enable link time optimization if you want functions in cpp files to be optimized
  • Rehno Lindeque
    Rehno Lindeque over 14 years
    Indeed, I have my suspicions that certain compilers very sneakily ignore 'inline' completely and only respond to '__inline' or '__force_inline'. I suppose this is to deter abuse!
  • Crashworks
    Crashworks over 14 years
    Not usually the case. inline is only a hint, but it's a hint most compilers take seriously. You can set the compiler to emit the assembly language along with the object code (/FAcs in Visual Studio, -s in GCC) to see exactly what it does. In my experience, both those compilers weigh the inline keyword quite heavily.
  • Pavel Minaev
    Pavel Minaev over 14 years
    It's interesting, because in my experience neither g++ nor VC weigh inline keyword at all. That is, if you see the function being inlined, and remove inline specifier from it, it will still get inlined. If you have any specific examples of the opposite, please share them!
  • Crashworks
    Crashworks over 14 years
    I meant the opposite case more: the compiler is free to inline anything it likes, but it's rare that I see it choose not to inline something I told it to inline. The typical case I use here is get/set functions (which I inline in the .h rather than define in a .cpp), and 3d vector operations. For some reason, functions like dot/cross product, orthonormalization, etc seem to be just at the threshold where MSVC won't inline them on its own, but will respect the inline keyword.
  • CB Bailey
    CB Bailey over 14 years
    inline is much more than a hint to the compiler. It changes the language rules about multiple definitions. Also, having static data isn't a cast iron reason to avoid inlining a function. The implementation is obliged to allocate a single static object for each function static whether or not the function is declared inline or not. Classes are still extensible if they have inline constructors and virtual destructors. And empty brace destructor is the one virtual function that it is sometimes a good idea to leave inline.
  • Gregory Pakosz
    Gregory Pakosz over 14 years
    It's a hint in the sense the function doesn't necessarily ends up inlined (but english isn't my mother tongue). About statics in functions marked inline, the result is that the function doesn't get inlined: you pay the price for the call and also each translation unit that includes and calls the function gets its own copy of the code and static variables. The reason for not inlining constructors and destructors when developing a library is binary compatibility with future versions of your library
  • CB Bailey
    CB Bailey over 14 years
    @Gregory: Functions with statics can be inlined, its just the actions on the static object which must refer to the same 'global' object; it's required by the standard. W.r.t. binary compatibility I agree with your reasons, but it's a whole other story. The fact that new private data members break binary compatibility usually puts other concerns in the shade. For long lived binary compatibility you often end up having to "pimpl" most interesting objects anyway, rendering the inline discussion irrelevant.
  • Rehno Lindeque
    Rehno Lindeque over 14 years
    I could be wrong I'm sure. I think I once saw '#define inline' in one of the standard header files, but it could have just been some backward compatibility flag for C. Also it is true that the compiler can inline any function it chooses to.
  • Rehno Lindeque
    Rehno Lindeque over 14 years
    I get the feeling that this is more of a happy coincidence than an intentional feature of C++. The idea is very similar to the 'static' global variables from C. It's a very interesting answer though. I wish they'd just used a keyword like 'internal' to indicate internal linkage.
  • Gregory Pakosz
    Gregory Pakosz over 14 years
    @Charles, I edited the answer. I had in mind old compilers treating an un-inlined function as if it had been declared static. Indeed conformant compilers will get it right but it was a "better safe than sorry" approach. Still the problem might arise when one misuses static on a function so that it becomes private instead of putting it in an anonymous namespace. About pimpl, agreed.
  • josesuero
    josesuero over 14 years
    It's inaccurate to call it a "hint to the compiler". In reality, non-inline functions can be inlined if the compiler feels like it. And inline functions won't be inlined if the compiler decides not to inline them. As Charles Bailey said, it changes the language rules. Rather than thinking of it as an optimization hint, it is more accurate to think of it as a completely different concept. The inline keyword tells the compiler to allow multiple definitions, and nothing else. The "inlining" optimization can be applied to almost any function, whether or not it's marked inline.
  • josesuero
    josesuero over 14 years
    +1. @Rehno: I'm not really sure what you're saying. What does linkage have to do with the inline keyword? And what is a happy coincidence?
  • josesuero
    josesuero over 14 years
    how does the inline keyword hinder "clear code"? The keyword in "premature optimization" is premature, not optimization. Saying that you should actively *avoid optimizations is just rubbish. The point of that quote is that you should avoid the optimizations that may not be necessary, and have harmful side effects on the code (such as making it less maintainable). I fail to see how the inline keyword is going to make the code less maintainable, or how it can be harmful to add it to a function.
  • josesuero
    josesuero over 14 years
    That's a different issue. You get the rebuild problem for code that is placed in a header file. Whether it is marked inline or not doesn't matter (other than without the inline keyword, you'll get linker errors - but the inline keyword is not the issue causing excessive rebuilds.
  • Thomas Matthews
    Thomas Matthews over 14 years
    However, changing an inline method will cause excessive builds versus changing a non-inline method in a shource file.
  • Gregory Pakosz
    Gregory Pakosz over 14 years
    I don't see how why my descriptive answer is summed up as "thinking of it as an optimization hint" and I may be blind but what you're saying in your comment about the compiler being fee to decide what gets inline and what not; I wrote it at the end of my answer. And as per thefreedictionary.com/hint a "hint" means "a slight indication"
  • josesuero
    josesuero over 14 years
    Yes, but the point is that it is not "a slight indication", but rather a way to get your code to compile and link successfully where it would otherwise result in an error. That is the purpose of the inline keyword.
  • Gregory Pakosz
    Gregory Pakosz over 14 years
    It's just that, when Stroustrup writes "the inline specifier is a hint to the compiler", I'm surprised I'm blamed for quoting him. Anyway, I spent enough time doing my best to back this answer with as much references as possible
  • Rehno Lindeque
    Rehno Lindeque over 14 years
    @jalf: Reading my comment in retrospect I realize it is rather vague and not that well thought out. Defining the same function in multiple files results a linker error which can be countered by declaring the function 'static'. However, 'inline' allows you to do the same thing with subtle differences that they do not actually get internal linkage like 'static' does. I suspect that this is actually more a coincidence because language implementers/designers realized that they'll need to do something special with functions declared in header files and that carried over to 'inline'.
  • dmazzoni
    dmazzoni over 14 years
    jalf, sometimes inlining a function will make your code slower, not faster. One example is when the function is called from several different places in your code; if the function is not inlined, then it might still be in the instruction cache when it's called from a different place, and the branch predictor might already be warmed up. There are some patterns that always improve efficiency, so it never hurts to use them. Inlining is not one of them. It usually has no effect on performance at all, it sometimes helps, and sometimes hurts. I stand behind my advice: profile first, then inline.
  • Crashworks
    Crashworks over 14 years
    Inlining is sometimes negative, but it can also be an immense performance gain under the right circumstances. I've measured it: assemblyrequired.crashworks.org/2009/01/19/…
  • Tracy
    Tracy over 11 years
    @Gregory Pakosz , why should we avoid inlining a I/O bounded function, i mean, CPU still has got to execute those I/O bounded codes, and btw, if code size enlargement is not considered, inlining does eliminate the function call overhead.
  • Gregory Pakosz
    Gregory Pakosz over 11 years
    @Tracy code is data, if it's I/O bound, inlining doesn't speed it up so don't pay the code cache trash tax
  • Lightness Races in Orbit
    Lightness Races in Orbit about 11 years
    @GregoryPakosz: But we don't all use inline in order to obtain function inlining. Sometimes we want the other benefits, like getting around ODR.
  • Destructor
    Destructor about 9 years
    @GregoryPakosz: Sir, what do you mean by saying that "Avoiding the cost of a function call is only half the story." ? Please explain it more clearly. are you saying about optimizations?
  • It'sPete
    It'sPete almost 9 years
    inline is still a hint. The compiler can fail to inline if it deems that your function is too bloated.
  • Admin
    Admin over 7 years
    One says inline is an order... the other says its a hint Would someone substantiate his statement so we can determine which one is true?
  • gast128
    gast128 almost 7 years
    Not sure why your comment got so many up votes, since performance is the dominant reason to use inline.
  • WARhead
    WARhead over 6 years
    @user2918461 i support the statement inline is just a hint. This has been supported by many websites and books
  • Volper
    Volper over 3 years
    @gert128 "Premature optimization is the root of all evil" if you're concerned about performance, just add -O3 to the compiler flags and the compiler will figure out what to inline by itself. Don't add keywords and expect them to make your code faster. I've heard a lecture about optimization and the lecturer who worked in LLVM said that the inline keyword doesn't have much to do with optimization. It's just about the semantics / language rules
  • Volper
    Volper over 3 years
    "Premature optimization is the root of all evil" if you're concerned about performance, just add -O3 to the compiler flags and the compiler will figure out what to inline by itself. Don't add keywords and expect them to make your code faster. I've heard a lecture about optimization and the lecturer who worked in LLVM said that the inline keyword doesn't have much to do with optimization. It's just about the semantics / language rules