Rust Performance Pitfalls
I have been doing some exploration of how well Rust optimizes Iterators and have been quite impressed.<p>Writing a iterator to provide the individual bits supplied by an iterator of bytes means you can count them with<p><pre><code>    fn count_bits&lt;I : Iterator&lt;Item=bool&gt;&gt;(it : I) -&gt; i32{
        let mut a=0;
        for i in it {
            if i {a+=1};
        }
        return a;
    } 
</code></pre>
Counting bits in an array of bytes would need something like this<p><pre><code>    let p:[u8;6] = [1,2,54,2,3,6];
    let result = count_bits(bits(p.iter().cloned()));
</code></pre>
Checking what that generates in asm <a href="https:&#x2F;&#x2F;godbolt.org&#x2F;g&#x2F;iTyfap" rel="nofollow">https:&#x2F;&#x2F;godbolt.org&#x2F;g&#x2F;iTyfap</a><p>The core of the code is<p><pre><code>    .LBB0_4:
        mov     esi, edx        ;edx has the current mask of the bit we are looking at
        and     esi, ecx        ;ecx is the byte we are examining
        cmp     esi, 1          ;check the bit to see if it is set (note using carry not zero flag)
        sbb     eax, -1         ;fun way to conditionally add 1
    .LBB0_1:
        shr     edx             ;shift mask to the next bit
        jne     .LBB0_4         ;if mask still has a bit in it, go do the next bit otherwise continue to get the next byte 
        cmp     rbx, r12        ;r12 has the memory location of where we should stop.   Are we there yet?
        je      .LBB0_5         ; if we are there, jump out. we&#x27;re all done
        movzx   ecx, byte ptr [rbx]  ;get the next byte
        inc     rbx             ; advance the pointer
        mov     edx, 128        ; set a new mask starting at the top bit
        jmp     .LBB0_4         ; go get the next bit
    .LBB0_5:
</code></pre>
Apart from magical bit counting instructions this is close to what I would have written in asm mysef.   That really impressed me.   I&#x27;m still a little wary of hitting a performance cliff. I worry that I can easily add something that will mean the optimiser bails on the whole chain, but so far I&#x27;m trusting Rust more than I have trusted any other Optimiser.<p>If this produces simiarly nice code (I haven&#x27;t checked yet)  I&#x27;ll be very happy<p><pre><code>   for (dest,source) in self.buffer.iter_mut().zip(data) { *dest=source }</code></pre>