When to use inline function and when not to use it?
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:
- To Inline or Not To Inline
- [9] Inline functions
- Policies/Binary Compatibility Issues With C++
- GotW #33: Inline
- Inline Redux
- Effective C++ - Item 33: Use inlining judiciously
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 offac()
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 constant720
for a callfac(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 aninline
function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate720
, another6 * fac(5)
, and yet another an un-inlined callfac(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 hasstatic
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.
Related videos on Youtube
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, 2020Comments
-
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 over 14 years
inline
is to the C++ newcomer whatCFLAGS
are to the Gentoo newcomer: no, compiling with-O3 -funroll-loops -finline-functions
won't make your old Pentium fly ;) -
Rob deFriesse over 14 yearsA 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 over 14 yearsDuplicate: stackoverflow.com/questions/1875947/…
-
David Thornley over 14 yearsYou 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 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 over 3 years@talekeDskobeDa you can enable link time optimization if you want functions in cpp files to be optimized
-
-
Rehno Lindeque over 14 yearsIndeed, 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 over 14 yearsNot 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 over 14 yearsIt'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 removeinline
specifier from it, it will still get inlined. If you have any specific examples of the opposite, please share them! -
Crashworks over 14 yearsI 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 theinline
keyword. -
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 declaredinline
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 over 14 yearsIt'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 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 over 14 yearsI 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 over 14 yearsI 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 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 misusesstatic
on a function so that it becomes private instead of putting it in an anonymous namespace. About pimpl, agreed. -
josesuero over 14 yearsIt's inaccurate to call it a "hint to the compiler". In reality, non-
inline
functions can be inlined if the compiler feels like it. Andinline
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. Theinline
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 markedinline
. -
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 over 14 yearshow 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 theinline
keyword is going to make the code less maintainable, or how it can be harmful to add it to a function. -
josesuero over 14 yearsThat'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 theinline
keyword, you'll get linker errors - but theinline
keyword is not the issue causing excessive rebuilds. -
Thomas Matthews over 14 yearsHowever, changing an inline method will cause excessive builds versus changing a non-inline method in a shource file.
-
Gregory Pakosz over 14 yearsI 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 over 14 yearsYes, 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 over 14 yearsIt'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 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 over 14 yearsjalf, 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 over 14 yearsInlining 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 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 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 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 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 almost 9 yearsinline is still a hint. The compiler can fail to inline if it deems that your function is too bloated.
-
Admin over 7 yearsOne 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 almost 7 yearsNot sure why your comment got so many up votes, since performance is the dominant reason to use inline.
-
WARhead over 6 years@user2918461 i support the statement inline is just a hint. This has been supported by many websites and books
-
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 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