<div dir="ltr"><div class="gmail_default" style="color:rgb(0,0,0)">I have been doing speed testing on our network frequently enough over the last five year that I have a good feel for these changes.  I have been benchmarking various means for copying files of 1.0-500 MB between workstations on our 1 Gbps LAN to local servers, and on our WAN which was just upgraded two months ago from a 7x T1 (11.5 Mbps) to 100 Mbps fiber. This is an all Windows network, workstations are Win7/10 and servers are Win Server 2003 (!!!), 2008, 2012 and 2016.</div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default" style="color:rgb(0,0,0)">The difference between open(dst).write(open(src).read()) and CopyFileW can be pretty signficant, especially for older Win server versions.  I see maybe 4x speedup using CopyFileW to those machines with larger files, so it's a big win.  On newer Windows Server versions it become sort of a wash, with both ways working better than anything else (much faster than command line utilities like DOS "copy" and Cygwin "cp", or Windows file explorer drag and drop, and very much faster than a C-code write(read()) loop).</div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default" style="color:rgb(0,0,0)">Here's an example I just ran for a Win Server 2003 copy.</div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default"><div class="gmail_default"><font color="#000000">2018-05-29T07:45:09 PDT</font></div><div class="gmail_default"><font color="#000000">---Using CopyFileW</font></div><div class="gmail_default"><font color="#000000">Copy 'xmas.mpg' to 'p:/build/' (28,872,704 bytes)</font></div><div class="gmail_default"><font color="#000000"> 1/3 -   0.27 s ( 905.2 Mbps)</font></div><div class="gmail_default"><font color="#000000"> 2/3 -   0.25 s ( 983.9 Mbps)</font></div><div class="gmail_default"><font color="#000000"> 3/3 -   0.26 s ( 968.6 Mbps)</font></div><div class="gmail_default"><font color="#000000">Theoretical:   0.25 s at 1000.0 Mbps</font></div><div class="gmail_default"><font color="#000000">Best time  :   0.25 s at  983.9 Mbps</font></div><div class="gmail_default"><font color="#000000"><br></font></div><div class="gmail_default"><font color="#000000">---Using write(read())</font></div><div class="gmail_default"><font color="#000000">Copy 'xmas.mpg' to 'p:/build/' (28,872,704 bytes)</font></div><div class="gmail_default"><font color="#000000"> 1/3 -   1.47 s ( 169.9 Mbps)</font></div><div class="gmail_default"><font color="#000000"> 2/3 -   1.21 s ( 205.0 Mbps)</font></div><div class="gmail_default"><font color="#000000"> 3/3 -   1.22 s ( 203.4 Mbps)</font></div><div class="gmail_default"><font color="#000000">Theoretical:   0.25 s at 1000.0 Mbps</font></div><div class="gmail_default"><font color="#000000">Best time  :   1.21 s at  205.0 Mbps</font></div></div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default" style="color:rgb(0,0,0)">On our WAN, which has a VPN endpoint 3000 miles from our office, routing back to a test server another 2000 miles inside the network (tracert shows 12-15 hops, 200 ms latency, arrrg), copying is slow no matter what: we are lucky to see 40 Mbps on a connection that has the slowest link section at 100 Mbps.  </div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default" style="color:rgb(0,0,0)">The biggest improvement we saw on WAN copies was when Ben Hoyt built scandir on top of Windows primitives.  We were doing a copytree using os.walk that would take almost 20 (twenty) minutes just to build the tree before it copied the first file. When scandir was first released, I rewrote my code with fingers crossed that it would help a bit.  On my first test, it took something like 15-20 seconds to build the tree and start copying.  I was sure I had screwed up and broken it, but was quite shocked when I saw that it was in fact working correctly.</div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default" style="color:rgb(0,0,0)">Bottom line is +1 on switching to OS-specific copy mechanisms.  Python is already the best* language for this sort of work (I've tried C/C++ and C# as alternatives), and this will make it even better.</div><div class="gmail_default" style="color:rgb(0,0,0)"><br></div><div class="gmail_default" style="color:rgb(0,0,0)">*Best for me in this particular case is "resulting code is fastest, ease of implementation is secondary."</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, May 29, 2018 at 1:59 AM Giampaolo Rodola' <<a href="mailto:g.rodola@gmail.com">g.rodola@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Whops, I hit "send" too soon. Sorry about the messed up message.<br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, May 29, 2018 at 10:56 AM, Giampaolo Rodola' <span dir="ltr"><<a href="mailto:g.rodola@gmail.com" target="_blank">g.rodola@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hello,</div><div>I've been working on a patch which speeds up shutil.copy* operations for all 3 major platforms (Linux, Windows, OSX):</div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline"><a href="https://bugs.python.org/issue33671" target="_blank">https://bugs.python.org/issue33671</a></span></div><div>Since the speedup is quite consistent I'd love to see this merged in, but considering shutil.copy* is quite crucial I wanted to hear other folk's opinion first. Attached patch attempts to use platform-specific zero-copy syscalls [1] by default and fallbacks on using plain read() / write() variant in case of immediate failure. In theory this should work fine, in practice I haven't tested it on exotic (e.g. network) filesystems. In order to diminish risks of breakage I think if it would make sense to:</div><div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">- add a global <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">shutil.NO_ZEROCOPY variable defaulting to False</span></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">- add a "no_zerocopy" argument to all functions involving a copy (copyfile(). copy(), copy2(), copytree(), move())</span></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial"><br></div><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial">Thoughts?<br></div><div><br></div>[1] sendfile() (Linux), fcopyfile() (OSX), CopyFileW (Windows)<br class="m_7051811802220187371m_-6589696259362747416gmail-Apple-interchange-newline"><br><div style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;text-decoration-style:initial;text-decoration-color:initial"><br></div><br></div><div><br></div><div>since the matter is a bit sensitive in terms of potential breakage on exotic / untested (e.g. network) filesystems I want to raise some attention about:</div><a href="https://bugs.python.org/issue33671" target="_blank">https://bugs.python.org/issue33671</a><div><div>Attached patch attempts to use platform-specific zero-copy syscalls by default and fallbacks on using plain read() / write() copy in case of immediate failure.  In order to diminish risks I think it would make sense to:</div><div>- add a global <span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">shutil.NO_ZEROCOPY variable defaulting to False</span></div><div><span style="color:rgb(34,34,34);font-family:arial,sans-serif;font-size:small;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">- add a "no_zerocopy" argument to all functions involving a copy (copyfile(). copy(), copy2(), copytree(), move())</span></div><div><br></div><div>Thoughts?<span class="m_7051811802220187371HOEnZb"><font color="#888888"><br></font></span></div><span class="m_7051811802220187371HOEnZb"><font color="#888888"><div><br></div>-- <br><div class="m_7051811802220187371m_-6589696259362747416gmail_signature"><div dir="ltr"><div>Giampaolo - <a href="http://grodola.blogspot.com" target="_blank">http://grodola.blogspot.com</a></div><div><br></div><div><br></div></div></div>
</font></span></div></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="m_7051811802220187371gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div>Giampaolo - <a href="http://grodola.blogspot.com" target="_blank">http://grodola.blogspot.com</a></div><div><br></div></div></div>
</div></div>
_______________________________________________<br>
Python-ideas mailing list<br>
<a href="mailto:Python-ideas@python.org" target="_blank">Python-ideas@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ideas" rel="noreferrer" target="_blank">https://mail.python.org/mailman/listinfo/python-ideas</a><br>
Code of Conduct: <a href="http://python.org/psf/codeofconduct/" rel="noreferrer" target="_blank">http://python.org/psf/codeofconduct/</a><br>
</blockquote></div>