Why is inlining considered faster than a function call?

前端 未结 16 1503
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-13 04:04

Now, I know it\'s because there\'s not the overhead of calling a function, but is the overhead of calling a function really that heavy (and worth the bloat of having it inli

相关标签:
16条回答
  • 2020-12-13 04:41

    Consider a simple function like:

    int SimpleFunc (const int X, const int Y)
    {
        return (X + 3 * Y); 
    }    
    
    int main(int argc, char* argv[])
    {
        int Test = SimpleFunc(11, 12);
        return 0;
    }
    

    This is converted to the following code (MSVC++ v6, debug):

    10:   int SimpleFunc (const int X, const int Y)
    11:   {
    00401020   push        ebp
    00401021   mov         ebp,esp
    00401023   sub         esp,40h
    00401026   push        ebx
    00401027   push        esi
    00401028   push        edi
    00401029   lea         edi,[ebp-40h]
    0040102C   mov         ecx,10h
    00401031   mov         eax,0CCCCCCCCh
    00401036   rep stos    dword ptr [edi]
    
    12:       return (X + 3 * Y);
    00401038   mov         eax,dword ptr [ebp+0Ch]
    0040103B   imul        eax,eax,3
    0040103E   mov         ecx,dword ptr [ebp+8]
    00401041   add         eax,ecx
    
    13:   }
    00401043   pop         edi
    00401044   pop         esi
    00401045   pop         ebx
    00401046   mov         esp,ebp
    00401048   pop         ebp
    00401049   ret
    

    You can see that there are just 4 instructions for the function body but 15 instructions for just the function overhead not including another 3 for calling the function itself. If all instructions took the same time (they don't) then 80% of this code is function overhead.

    For a trivial function like this there is a good chance that the function overhead code will take just as long to run as the main function body itself. When you have trivial functions that are called in a deep loop body millions/billions of times then the function call overhead begins to become large.

    As always, the key is profiling/measuring to determine whether or not inlining a specific function yields any net performance gains. For more "complex" functions that are not called "often" the gain from inlining may be immeasurably small.

    0 讨论(0)
  • 2020-12-13 04:43

    Because there's no call. The function code is just copied

    0 讨论(0)
  • 2020-12-13 04:46

    Aside from the fact that there's no call (and therefore no associated expenses, like parameter preparation before the call and cleanup after the call), there's another significant advantage of inlining. When the function body is inlined, it's body can be re-interpreted in the specific context of the caller. This might immediately allow the compiler to further reduce and optimize the code.

    For one simple example, this function

    void foo(bool b) {
      if (b) {
        // something
      }
      else {
        // something else
      }
    }
    

    will require actual branching if called as a non-inlined function

    foo(true);
    ...
    foo(false);
    

    However, if the above calls are inlined, the compiler will immediately be able to eliminate the branching. Essentially, in the above case inlining allows the compiler to interpret the function argument as a compile-time constant (if the parameter is a compile-time constant) - something that is generally not possible with non-inlined functions.

    However, it is not even remotely limited to that. In general, the optimization opportunities enabled of inlining are significantly more far-reaching. For another example, when the function body is inlined into the specific caller's context, the compiler in general case will be able to propagate the known aliasing-related relationships present in the calling code into the inlined function code, thus making it possible to optimize the function's code better.

    Again, the possible examples are numerous, all of them stemming from the basic fact that inlined calls are immersed into the specific caller's context, thus enabling various inter-context optimizations, which would not be possible with non-inlined calles. With inlining you basically get many individual versions of your original function, each version is tailored and optimized individually for each specific caller context. The price of that is, obviously, the potential danger of code bloat, but if used correctly, it can provide noticeable performance benefits.

    0 讨论(0)
  • 2020-12-13 04:46

    Because no jump is performed.

    0 讨论(0)
提交回复
热议问题