title: When RVO shows the maximum performance impact?
body: <p>I've spent a little time trying to understand is RVO performance impact is as valuable as I thought.</p>
  
  <p>Here is my benchmark code (the main idea is to create big structures and return them from functions):</p>
  
  <pre><code>#include &lt;chrono&gt;
  #include &lt;iostream&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;time.h&gt;
  #define SIZE_MEDIUM 128
  #define SIZE_LARGE  8192
  #define ITER_COUNT  100000
  using namespace std;
  using namespace std::chrono;
  
  struct MediumStruct {
      int data[SIZE_MEDIUM];
  };
  struct LargeStruct {
      int data[SIZE_LARGE];
  };
  
  template&lt;typename T&gt;
  T by_value(int size) {
      T rv;
      for (int i = 0; i &lt; size; i++) {
          rv.data[i] = rand();
      }
      return rv;
  }
  
  template&lt;typename T&gt;
  void by_ref(T &amp;v, int size) {
      for (int i = 0; i &lt; size; i++) {
          v.data[i] = rand();
      }
  }
  
  template&lt;typename T&gt;
  void bench_by_value(int size, const string &amp;suite) {
      high_resolution_clock::time_point t1 = high_resolution_clock::now();
  
      int counter = 0;
      for (int i = 0; i &lt; ITER_COUNT; i++) {
          T r = by_value&lt;T&gt;(size);
          for (int j = 0; j &lt; size; j++) {
              counter += r.data[j];
          }
      }
  
      high_resolution_clock::time_point t2 = high_resolution_clock::now();
      auto duration = duration_cast&lt;milliseconds&gt;(t2 - t1).count();
      cout &lt;&lt; "By value (" &lt;&lt; suite &lt;&lt; ") " &lt;&lt; duration &lt;&lt; " ms " 
           &lt;&lt; "[stub " &lt;&lt; counter &lt;&lt; "]" &lt;&lt; endl;
  }
  
  template&lt;typename T&gt;
  void bench_by_ref(int size, const string &amp;suite) {
      high_resolution_clock::time_point t1 = high_resolution_clock::now();
  
      int counter = 0;
      for (int i = 0; i &lt; ITER_COUNT; i++) {
          T r;
          by_ref&lt;T&gt;(r, size);
          for (int j = 0; j &lt; size; j++) {
              counter += r.data[j];
          }
      }
  
      high_resolution_clock::time_point t2 = high_resolution_clock::now();
      auto duration = duration_cast&lt;milliseconds&gt;(t2 - t1).count();
      cout &lt;&lt; "By ref (" &lt;&lt; suite &lt;&lt; ") " &lt;&lt; duration &lt;&lt; " ms " 
           &lt;&lt; "[stub " &lt;&lt; counter &lt;&lt; "]" &lt;&lt; endl;
  }
  
  int main() {
      srand(time(NULL));
      bench_by_value&lt;MediumStruct&gt;(SIZE_MEDIUM, "MEDIUM");
      bench_by_value&lt;LargeStruct&gt;(SIZE_LARGE, "LARGE");
      bench_by_ref&lt;MediumStruct&gt;(SIZE_MEDIUM, "MEDIUM");
      bench_by_ref&lt;LargeStruct&gt;(SIZE_LARGE, "LARGE");
  }
  </code></pre>
  
  <p>On my MacBook Pro this benchmark shows pretty the same performance with and without RVO optimization.</p>
  
  <pre><code>$g++ --version
  Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
  Apple LLVM version 7.3.0 (clang-703.0.31)
  Target: x86_64-apple-darwin15.2.0
  Thread model: posix
  InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
  
  $g++ -std=c++11 -S -o /dev/stdout main.cpp | grep memcpy | wc -l
         0
  
  $g++ -std=c++11 -fno-elide-constructors -S -o /dev/stdout main.cpp | grep memcpy | wc -l
         4
  
  $ g++ -std=c++11 main.cpp
  $ ./a.out
  By value (MEDIUM) 123 ms [stub -1593461165]
  By value (LARGE) 7741 ms [stub -1299931242]
  By ref (MEDIUM) 120 ms [stub -1955762550]
  By ref (LARGE) 7835 ms [stub 911248215]
  $ ./a.out
  By value (MEDIUM) 118 ms [stub 2094615909]
  By value (LARGE) 7840 ms [stub -1276864738]
  By ref (MEDIUM) 118 ms [stub -223778153]
  By ref (LARGE) 7890 ms [stub -381745773]
  
  $ g++ -std=c++11 -fno-elide-constructors main.cpp
  $ ./a.out
  By value (MEDIUM) 122 ms [stub 1921645226]
  By value (LARGE) 8078 ms [stub 1869896539]
  By ref (MEDIUM) 123 ms [stub -676968691]
  By ref (LARGE) 7855 ms [stub 1621698360]
  $ ./a.out
  By value (MEDIUM) 119 ms [stub 954834819]
  By value (LARGE) 7779 ms [stub 98742842]
  By ref (MEDIUM) 118 ms [stub 1498384025]
  By ref (LARGE) 7505 ms [stub -118604845]
  </code></pre>
  
  <p>Having such results one might tend to always use returning by value technique since it looks better semantically even if a compiler doesn't provide RVO. When RVO really gives significant performance impact?</p>
  
  <p>Link to the benchmark <a href="https://gist.github.com/Ostrovski/09bdcacab4f7ccb94cf05138833f3fd6" rel="nofollow">gist</a>.</p>