title: why is inlined function slower than function pointer?
body: <p>Consider the following code:</p>
  
  <pre><code>typedef void (*Fn)();
  
  volatile long sum = 0;
  
  inline void accu() {
      sum+=4;
  }
  
  static const Fn map[4] = {&amp;accu, &amp;accu, &amp;accu, &amp;accu};
  
  int main(int argc, char** argv) {
      static const long N = 10000000L;
      if (argc == 1)
      {
              for (long i = 0; i &lt; N; i++)
              {
                      accu();
                      accu();
                      accu();
                      accu();
              }
      }
      else
      {
              for (long i = 0; i &lt; N; i++)
              {
                      for (int j = 0; j &lt; 4; j++)
                              (*map[j])();
              }
      }
  }
  </code></pre>
  
  <p>When I compiled it with:</p>
  
  <pre><code>g++ -O3 test.cpp
  </code></pre>
  
  <p>I'm expecting the first branch to run faster because the compiler could inline the function call to accu. And the second branch cannot be inlined because accu is called through function pointer stored in an array.</p>
  
  <p>But the results surprised me:</p>
  
  <pre><code>time ./a.out 
  
  real    0m0.108s
  user    0m0.104s
  sys 0m0.000s
  
  time ./a.out 1
  
  real    0m0.095s
  user    0m0.088s
  sys 0m0.004s
  </code></pre>
  
  <p>I don't understand why, so I did an objdump:</p>
  
  <pre><code>objdump -DStTrR a.out &gt; a.s
  </code></pre>
  
  <p>and the disassembly doesn't seem to explain the performance result I got:</p>
  
  <pre><code>8048300 &lt;main&gt;:
  8048300:       55                      push   %ebp
  8048301:       89 e5                   mov    %esp,%ebp
  8048303:       53                      push   %ebx
  8048304:       bb 80 96 98 00          mov    $0x989680,%ebx
  8048309:       83 e4 f0                and    $0xfffffff0,%esp
  804830c:       83 7d 08 01             cmpl   $0x1,0x8(%ebp)
  8048310:       74 27                   je     8048339 &lt;main+0x39&gt;
  8048312:       8d b6 00 00 00 00       lea    0x0(%esi),%esi
  8048318:       e8 23 01 00 00          call   8048440 &lt;_Z4accuv&gt;
  804831d:       e8 1e 01 00 00          call   8048440 &lt;_Z4accuv&gt;
  8048322:       e8 19 01 00 00          call   8048440 &lt;_Z4accuv&gt;
  8048327:       e8 14 01 00 00          call   8048440 &lt;_Z4accuv&gt;
  804832c:       83 eb 01                sub    $0x1,%ebx
  804832f:       90                      nop
  8048330:       75 e6                   jne    8048318 &lt;main+0x18&gt;
  8048332:       31 c0                   xor    %eax,%eax
  8048334:       8b 5d fc                mov    -0x4(%ebp),%ebx
  8048337:       c9                      leave
  8048338:       c3                      ret
  8048339:       b8 80 96 98 00          mov    $0x989680,%eax
  804833e:       66 90                   xchg   %ax,%ax
  8048340:       8b 15 18 a0 04 08       mov    0x804a018,%edx
  8048346:       83 c2 04                add    $0x4,%edx
  8048349:       89 15 18 a0 04 08       mov    %edx,0x804a018
  804834f:       8b 15 18 a0 04 08       mov    0x804a018,%edx
  8048355:       83 c2 04                add    $0x4,%edx
  8048358:       89 15 18 a0 04 08       mov    %edx,0x804a018
  804835e:       8b 15 18 a0 04 08       mov    0x804a018,%edx
  8048364:       83 c2 04                add    $0x4,%edx
  8048367:       89 15 18 a0 04 08       mov    %edx,0x804a018
  804836d:       8b 15 18 a0 04 08       mov    0x804a018,%edx
  8048373:       83 c2 04                add    $0x4,%edx
  8048376:       83 e8 01                sub    $0x1,%eax
  8048379:       89 15 18 a0 04 08       mov    %edx,0x804a018
  804837f:       75 bf                   jne    8048340 &lt;main+0x40&gt;
  8048381:       eb af                   jmp    8048332 &lt;main+0x32&gt;
  8048383:       90                      nop
  ...
  8048440 &lt;_Z4accuv&gt;:
  8048440:       a1 18 a0 04 08          mov    0x804a018,%eax
  8048445:       83 c0 04                add    $0x4,%eax
  8048448:       a3 18 a0 04 08          mov    %eax,0x804a018
  804844d:       c3                      ret
  804844e:       90                      nop
  804844f:       90                      nop
  </code></pre>
  
  <p>It seems the direct call branch is definitely doing less than the function pointer branch.
  But why does the function pointer branch run faster than the direct call?</p>
  
  <p>And note that I only used "time" for measuring the time. I've used clock_gettime to do the measurement and got similar results.</p>