<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div></div><div>Big thanks for doing the measurements!</div><div><br></div><div>-Thorsten&nbsp;</div><div><br>Am 11.12.2015 um 00:36 schrieb David Owens II &lt;<a href="mailto:david@owensd.io">david@owensd.io</a>&gt;:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8"><div class="">Here’s my basic test case:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">let&nbsp;first =&nbsp;10000000</font></div><div class=""><font face="Menlo" class="">let&nbsp;second =&nbsp;20000000</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">class&nbsp;LoopPerfTests:&nbsp;XCTestCase&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;func&nbsp;testZipStride() {</font></div><div class=""><span style="font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span><span style="font-family: Menlo;" class="">self</span><span style="font-family: Menlo;" class="">.</span><span style="font-family: Menlo;" class="">measureBlock</span><span style="font-family: Menlo;" class="">&nbsp;{</span></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;var&nbsp;sum =&nbsp;0</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(i, j)&nbsp;in&nbsp;zip(first.stride(to:&nbsp;0, by: -1),&nbsp;second.stride(to:&nbsp;0, by: -2)) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;i %&nbsp;2&nbsp;==&nbsp;0&nbsp;{&nbsp;continue&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;sum +=&nbsp;1</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(sum)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;func&nbsp;testCStyleFor() {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.measureBlock&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;var&nbsp;sum =&nbsp;0</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;var&nbsp;i =&nbsp;first, j =&nbsp;second; i &gt;&nbsp;0&nbsp;&amp;&amp; j &gt;&nbsp;0; i -=&nbsp;1, j -=&nbsp;2&nbsp;{</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;i %&nbsp;2&nbsp;==&nbsp;0&nbsp;{&nbsp;continue&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;sum +=&nbsp;1</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;print(sum)</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;&nbsp;}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><br class=""></div><div class="">Non-optimized timings:</div><div class=""><ul class=""><li class="">testCStyleFor - 0.126s</li><li class="">testZipStride - 2.189s</li></ul></div><div class=""><br class=""></div><div class="">Optimized timings:</div><div class=""><div class=""><ul class=""><li class="">testCStyleFor - 0.008s</li><li class="">testZipStride - 0.015s</li></ul></div></div><div class=""><br class=""></div><div class="">That’s a lot worse than 34%; even in optimized builds, that’s 2x slower and in debug builds, that’s 17x slower. I think it’s unreasonable to force people to write a more verbose while-loop construct to simply get the performance they need.</div><div class=""><br class=""></div><div class="">Also, the readability argument is very subjective; for example, I don’t find the zip version more readability. In fact, I think it obscures what the logic of the loop is doing. But again, that’s subjective.</div><div class=""><br class=""></div><div class="">-David</div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 2:41 PM, Paul Cantrell &lt;<a href="mailto:cantrell@pobox.com" class="">cantrell@pobox.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class="">Is there any guarantee that these two loops have the exact same runtime performance?</div><div class=""><div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Menlo" class="">for (i, j) in zip(10.stride(to: 0, by: -1), 20.stride(to: 0, by: -2)) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;if i % 2 == 0 { continue }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;print(i, j)</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">for var i = 10, j = 20; i &gt; 0 &amp;&amp; j &gt; 0; i -= 1, j -= 2 {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;if i % 2 == 0 { continue }</font></div><span class="" style="font-family: Menlo;">&nbsp; &nbsp;print(i, j)</span><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><blockquote type="cite" class=""></blockquote><blockquote type="cite" class=""></blockquote></div></div></div></div></blockquote></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">In a quick and dirty test, the second is approximately 34% slower.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I’d say that’s more than acceptable for the readability gain. If you’re in that rare stretch of critical code where the extra 34% actually matters, write it using a while loop instead.</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">P</div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 4:07 PM, David Owens II via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 1:57 PM, thorsten--- via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Yes, performance is one thing neglected by the discussions and the proposal.</span><br class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></div></blockquote></div><br class=""><div class="">This is my primary objection to to this proposal; it assumes (or neglects?) that all of the types used can magically be inlined to nothing but the imperative code. This isn’t magical, someone has to implement the optimizations to do this.</div><div class=""><br class=""></div><div class="">Is there any guarantee that these two loops have the exact same runtime performance?</div><div class=""><div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><font face="Menlo" class="">for (i, j) in zip(10.stride(to: 0, by: -1), 20.stride(to: 0, by: -2)) {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;if i % 2 == 0 { continue }</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;print(i, j)</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">for var i = 10, j = 20; i &gt; 0 &amp;&amp; j &gt; 0; i -= 1, j -= 2 {</font></div><div class=""><font face="Menlo" class="">&nbsp; &nbsp;if i % 2 == 0 { continue }</font></div><span class="" style="font-family: Menlo;">&nbsp; &nbsp;print(i, j)</span><div class=""><font face="Menlo" class="">}</font></div></blockquote><div class=""><blockquote type="cite" class=""></blockquote><blockquote type="cite" class=""></blockquote></div><div class=""><br class=""></div><div class="">And can you guarantee that performance is relatively the same across debug and release builds? Because historically, Swift has suffered greatly in this regard with respects to the performance of optimized versus non-optimized builds.</div></div><div class=""><br class=""></div><div class="">These types of optimizer issues are real-world things I’ve had to deal with (and have written up many blog posts about). I get the desire to simplify the constructs, but we need an escape hatch to write performant code when the optimizer isn’t up to the job.</div><div class=""><br class=""></div><div class="">-David</div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=zCg-2FSGF9Wk188a6c55kLyEbrj7YhaXxFEHM-2F-2B0YAlzVbqZGAg4i3SBvgPUw5uEFQbr8fEPwqqUFQb7VZ4tlBpU-2FZ9Wdcv90oH0fJ5jP-2Bd-2BnfAB5xQ-2FM8ILhQ3CMsUuyVyp8wO2XudWrUmtfVjPbV7-2FcRr-2F8nfR2mO0llGnjqSoJp9kM8-2FYGDP5kOXzyQ-2FlA6CTMKS3GoaGJ19o1vTnpVZE3I-2B2L-2FHgQNqIkOBllOTIE-3D" alt="" width="1" height="1" border="0" class="" style="height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;"></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div></div></blockquote></div><br class=""></div></blockquote></body></html>