Wednesday, December 30, 2020

inline in C++

Keyword

 It's a common myth that the inline specifier in C++ is ignored by the compiler. While the standard states that it's only a hint for the compiler at least on Visual Studio 2019 the inlining process is influenced by the keyword.

Test case

 For the test case the following class is used:


struct Dummy
{
    explicit      Dummy       (int n);
    
    int           Get         () const;  // defined in cpp
    int           GetInline   () const;

private:
    int           m_n;
};

inline int Dummy::GetInline() const
{
   return m_n;
}

Assembly

  The use of inlining by the compiler can be studied by looking at the produced assembly in release mode. Tip to use DebugBreak() under debugger to stop around call location.

For normal function invocations it looks like:


00007FF71ECF166C  lea         rcx,[rsp+30h]  
00007FF71ECF1671  call        Dummy::Get (07FF71ECF1730h)  
00007FF71ECF1676
00007FF71ECF167C
00007FF71ECF1680  add         ecx,eax  

 The inlined version looks like:


00007FF71ECF1676
00007FF71ECF167C  add         ecx,dword ptr [rsp+38h]  

 For function invocation a call instruction is issued while the inlined version uses an add of the memory content to register ecx. The assembly code for the non inlined function definition is a plain memory copy instruction so performance wise the call is just overhead.

Results

 Tests take place on Visual Studio 2019 version 16.8.3 with a x64 build in release mode. The following cases are tested:

  1. use class inside a module
  2. use class inside a module with /LTCG (i.e. 'link time code generation')
  3. use exported class (i.e. the class is exported from a DLL and used in another module)

The results are as follow:

Case Get GetInline
use inside a module not inlined inlined
use inside a module with /LTCG inlined inlined
use exported class not inlined inlined

Conclusion

  The inline keyword is not ignored by Visual Studio 2019 and used as a hint. Recommendation to use it where applicable (e.g. one line 'getters' and performance intensive use cases). 

  The use of inline in a DLL context is food for discussion but it's okay as long as you rebuild the DLL (and its clients) when you change the source code of the DLL. MFC and boost are standard examples. 

 Other aspects not discussed here are use in (exported) templates and constexpr constructors (with noexcept).

External links

  •  https://devblogs.microsoft.com/cppblog/inlining-decisions-in-visual-studio/

No comments:

Post a Comment

Careful with std::ranges

<ranges>   C++20 has added the the ranges library. Basically it works on ranges instead of iterators but added some subtle constraint...