<story><title>Rust vs. C++: Fine-grained Performance</title><url>http://cantrip.org/rust-vs-c++.html</url></story><parent_chain></parent_chain><comment><author>zvrba</author><text>Most insightful part for me was this one:&lt;p&gt;&amp;gt; Many variations [he&amp;#x27;s talking about Rust] that seemed like they ought to run the same speed or faster turned out slower, often much slower. By contrast, in C++ it was surprisingly difficult to discover a way to express the same operations differently and get a different run time.&lt;p&gt;This is an insidious pitfall that may earn Rust the &amp;quot;slow&amp;quot; label, akin to what happened to Common Lisp.</text></comment>
<story><title>Rust vs. C++: Fine-grained Performance</title><url>http://cantrip.org/rust-vs-c++.html</url></story><parent_chain></parent_chain><comment><author>nkurz</author><text>&lt;i&gt;Curiously, most variations of the C++ version run only half as fast as they should on Intel Haswell chips, probably because of branch prediction failures&lt;/i&gt;&lt;p&gt;I haven&amp;#x27;t looked at the code yet (time for bed) but this note from Agner seems like it might be relevant:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  3.8 Branch prediction in Intel Haswell, Broadwell and Skylake

  The branch predictor appears to have been redesigned in the 
  Haswell, but very little is known about its construction.

  The measured throughput for jumps and branches varies 
  between one branch per clock cycle and one branch per two 
  clock cycles for jumps and predicted taken branches. 
  Predicted not taken branches have an even higher throughput   
  of up to two branches per clock cycle.

  The high throughput for taken branches of one per clock was 
  observed for up to 128 branches with no more than one 
  branch per 16 bytes of code. If there is more than one 
  branch per 16 bytes of code then the throughput is reduced 
  to one jump per two clock cycles. If there are more than 
  128 branches in the critical part of the code, and if they 
  are spaced by at least 16 bytes, then apparently the first 
  128 branches have the high throughput and the remaining 
  have the low throughput.

  These observations may indicate that there are two branch 
  prediction methods: a fast method tied to the μop cache and 
  the instruction cache, and a slower method using a branch 
  target buffer.
&lt;/code&gt;&lt;/pre&gt;
&lt;a href=&quot;http:&amp;#x2F;&amp;#x2F;www.agner.org&amp;#x2F;optimize&amp;#x2F;microarchitecture.pdf&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;www.agner.org&amp;#x2F;optimize&amp;#x2F;microarchitecture.pdf&lt;/a&gt;&lt;p&gt;At a glance, the symptoms seem like this might match.  Separately, I think there is still a limit of 3 branches per 16B before the branch prediction starts to fail.  It&amp;#x27;s rare to hit this in normal code, but something this optimized might.</text></comment>