Boost logo

Boost Users :

Subject: Re: [Boost-users] Library Developers Battling Cyclic Header Dependency
From: Simonson, Lucanus J (lucanus.j.simonson_at_[hidden])
Date: 2011-03-16 19:19:16


Steven Watanabe wrote:
> AMDG
>
> On 03/16/2011 03:09 PM, Simonson, Lucanus J wrote:
>> By the way, for functions defined in a header file without inline
>> keyword the compiler has the option to inline them. Only if the
>> compiler chooses not to inline the function will it caues a link
>> error if there are multiple object files that contain that function
>> definition.
>
> Doesn't the compiler have to emit
> a definition even if it decides to inline it?

I suppose it depends upon the compiler. My experience was that I don't get the link error if I omit the inline keyword if the compiler fully inlines all usage of the function and in that case there is neither strong nor weak symbol for the function in the symbol table of the object file and therefore no link error later. However, as soon as the compiler doesn't inline the function somewhere in the object file it shows up in the symbol table and results in link error if it is also in the symbol table of another object file and the inline keyword was omitted resulting in strong symbol. That is why I declare all header file function definitions inline so that link errors don't sneak up on me. You always have the symbol if you compile in debug mode, of course, so the link error will show up right away in the debug build, but not always in the optimized build.

The normal way I check how successful the compiler is in inlining functions I intend to be inlined (including template functions) is check for the existence of the weak symbol in the object file of an optimized build. I have seen huge volumes of my code compiled into a benchmark application with only main() in the symbol table. Profiling at that point turned out to be useless because 100% of runtime was attributed to main. Since function call overhead was the thing we were trying to optimize, however, we were satisfied with that result.

By the way, avoiding calling the same function you want to be inlined multiple times from another function, minimizing the call stack depth of functions you want inlined and passing even built in types by reference instead of by value seem to be the most important factors in determining whether functions get inlined as desired. Since we rely on the compiler to inline template code and make our abstraction zero cost it becomes important to understand why the compiler fails, at least empirically, so that we can change our code to reclaim that performance loss. Here we are talking specifically about and older version of gcc, but in general all compilers follow the same heuristics to try to balance performance improvement, object code size and compile time.

Regards,
Luke


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net