<div dir="ltr">I&#39;ve written a simple wrapper sequence that should be optimized out, and performed a couple of microbenchmarks. Code:<div><br></div><div>===begin===</div><div><div>struct WrapperSequence&lt;S: Sequence&gt; : Sequence {</div><div>    let base: S</div><div>    init(_ base: S) { self.base = base }</div><div>    func makeIterator() -&gt; S.Iterator { return base.makeIterator() }</div><div>}</div><div><br></div><div>func predicate(num: Int) -&gt; Bool {</div><div>    return true</div><div>}</div><div><br></div><div>let sequence = WrapperSequence(1...400000000).lazy.filter(predicate)  // or remove WrapperSequence</div><div>let array = Array(sequence)</div><div>===end===</div><div><br></div><div>Results:</div><div><br></div><div>1. Double-pass wins: num % 2 == 0</div><div>2. Single-pass wins: num % 2 == 0 &amp;&amp; num % 3 == 0</div><div>3. Double-pass wins: num % 2 == 0 || num % 3 == 0</div></div>4. Double-pass wins: num % 2 == 0 || num % 3 == 0 || num % 5 == 0 || num % 7 == 0 || num % 11 == 0<div>5. Single-pass wins: num % 2 == 0 || num % 3 == 0 || num % 5 == 0 || num % 7 == 0 || num % 11 == 0 || num % 13 == 0</div><div><br></div><div>But I have to admit that double-pass algorithm CAN be faster if the one knows what he is doing.</div><div>I conclude that we need an API to choose between the two algorithms, and single-pass should be the safe default.</div><div><br></div><div>- Anton</div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-06-19 19:56 GMT+03:00 Антон Жилин <span dir="ltr">&lt;<a href="mailto:antonyzhilin@gmail.com" target="_blank">antonyzhilin@gmail.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">It&#39;s not a bug.  Measuring the length of the source before allocating<br>the destination array is usually a big win when compared to repeatedly<br>growing the array&#39;s memory and copying all its elements.<br>-- <br>-Dave</blockquote><div><br></div><div>Usually yes, but not in the case of lazy filter. If predicate contains anything more than a dozen CPU instructions, single-pass version is faster.</div><div><br></div><div>We often want the predicate to have side effects, but we cannot with current implementation: the side effects will be doubled.</div><div><br></div><div>I also wonder if it&#39;s possible to allocate array with capacity of underlying collection (before all lazy stuff) and shrink it in the end.</div><div><br></div><div>- Anton</div></div>
</blockquote></div><br></div>