You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Efficient zero-copy for shutil.copy* functions (Linux, OSX and Win) #77852
Patch in attachment uses platform specific zero-copy syscalls on Linux and Solaris (os.sendfile(2)), Windows (CopyFileW) and OSX (fcopyfile(2)) speeding up shutil.copyfile() and other functions using it (copy(), copy2(), copytree(), move()).
Average speedup for a 512MB file copy is +24% on Linux, +50% on OSX and +48% on Windows by copying file on the same partition (SSD disk was used).
without patch:
1 loop, best of 5: 953 msec per loop
real 0m5.930s
user 0m1.021s
sys 0m4.835s
with patch:
1 loop, best of 5: 480 msec per loop
real 0m3.150s
user 0m0.067s
sys 0m2.740s
Windows
=======
128K copy (+69%):
without patch:
50 loops, best of 5: 6.45 msec per loop
with patch:
50 loops, best of 5: 1.99 msec per loop
8M copy (+64%):
without patch:
10 loops, best of 5: 22.6 msec per loop
with patch:
50 loops, best of 5: 7.95 msec per loop
512M copy (+48%):
without patch:
1 loop, best of 5: 1.21 sec per loop
with patch:
1 loop, best of 5: 629 msec per loop
changed the title [-]Efficient efficient zero-copy syscalls for shutil.copy* functions (Linux, OSX and Win)[/-][+]Efficient zero-copy for shutil.copy* functions (Linux, OSX and Win)[/+]on May 28, 2018
Apart from the usual bit of minor style issues, I couldn't see anything inherently wrong with the PR, but I'll leave the detailed reviews to those who'd have to maintain the code in the future. :)
New changeset 4a172cc by Giampaolo Rodola in branch 'master': bpo-33671: efficient zero-copy for shutil.copy* functions (Linux, OSX and Win) (bpo-7160) 4a172cc
For future reference, as per #7160 discussion, we decided not to use CopyFileEx on Windows and instead increase read() buffer size from 16KB to 1MB (Windows only) resulting in a 40.8% speedup (instead of 48%). Also copyfileobj() has been optimized on all platforms by using readinto()/memoryview()/bytearray().
Updated benchmarks on Windows:
128KB copy (+27%)
without patch:
50 loops, best of 5: 7.69 sec per loop
with patch:
50 loops, best of 5: 5.61 sec per loop
8MB copy (+45.6%)
without patch:
10 loops, best of 5: 20.8 sec per loop
with patch:
20 loops, best of 5: 11.3 sec per loop
512MB copy (+40.8%)
without patch:
1 loop, best of 5: 1.26 sec per loop
with patch:
1 loop, best of 5: 646 msec per loop
New changeset c7f02a9 by Giampaolo Rodola in branch 'master': bpo-33671 / shutil.copyfile: use memoryview() with dynamic size on Windows (bpo-7681) c7f02a9
Activity
giampaolo commentedon May 28, 2018
Patch in attachment uses platform specific zero-copy syscalls on Linux and Solaris (os.sendfile(2)), Windows (CopyFileW) and OSX (fcopyfile(2)) speeding up shutil.copyfile() and other functions using it (copy(), copy2(), copytree(), move()).
Average speedup for a 512MB file copy is +24% on Linux, +50% on OSX and +48% on Windows by copying file on the same partition (SSD disk was used).
Follows some benchmarks.
Setup
=====
Create 128K, 8M, 512M file:
Benchmark:
Linux
=====
128K copy (+13%):
8MB copy (+24%):
512MB copy (+26%):
OSX
===
128K copy (+8.5%):
8MB copy (+67%):
512MB copy (+50%):
Windows
=======
128K copy (+69%):
8M copy (+64%):
512M copy (+48%):
[-]Efficient efficient zero-copy syscalls for shutil.copy* functions (Linux, OSX and Win)[/-][+]Efficient zero-copy for shutil.copy* functions (Linux, OSX and Win)[/+]giampaolo commentedon May 28, 2018
PR: #7160
scoder commentedon May 28, 2018
Nice, I really like this.
Apart from the usual bit of minor style issues, I couldn't see anything inherently wrong with the PR, but I'll leave the detailed reviews to those who'd have to maintain the code in the future. :)
scoder commentedon May 28, 2018
Regarding the benchmarks, just to be sure, did you try reversing the run order to make sure you don't get unfair caching effects for the later runs?
socketpair commentedon May 28, 2018
http://man7.org/linux/man-pages/man2/ioctl_ficlonerange.2.html
That possibly should be used under Linux in order to really acheive zero-copying. Just like modern cp command.
giampaolo commentedon May 29, 2018
Yes, I tried changing benchmarks order and zero-copy variants are always faster. As for instantaneous CoW copy, it is debatable. E.g. "cp" command does not do it by default:
https://unix.stackexchange.com/questions/80351/why-is-cp-reflink-auto-not-the-default-behaviour
I think shutil should follow the same lead, and perhaps provide a cow=bool argument in the future.
giampaolo commentedon Jun 12, 2018
New changeset 4a172cc by Giampaolo Rodola in branch 'master':
bpo-33671: efficient zero-copy for shutil.copy* functions (Linux, OSX and Win) (bpo-7160)
4a172cc
giampaolo commentedon Jun 12, 2018
For future reference, as per #7160 discussion, we decided not to use CopyFileEx on Windows and instead increase read() buffer size from 16KB to 1MB (Windows only) resulting in a 40.8% speedup (instead of 48%). Also copyfileobj() has been optimized on all platforms by using readinto()/memoryview()/bytearray().
Updated benchmarks on Windows:
128KB copy (+27%)
8MB copy (+45.6%)
512MB copy (+40.8%)
StyXman commentedon Jun 13, 2018
Thanks Gianpaolo for pushing for this. Great job.
vstinner commentedon Jun 13, 2018
I concur: great job! Cool optimization.
giampaolo commentedon Jun 19, 2018
New changeset c7f02a9 by Giampaolo Rodola in branch 'master':
bpo-33671 / shutil.copyfile: use memoryview() with dynamic size on Windows (bpo-7681)
c7f02a9
vstinner commentedon Jun 22, 2018
New changeset 8fbbdf0 by Victor Stinner in branch 'master':
bpo-33671: Add support.MS_WINDOWS and support.MACOS (GH-7800)
8fbbdf0
vstinner commentedon Jun 26, 2018
New changeset 937ee9e by Victor Stinner in branch 'master':
Revert "bpo-33671: Add support.MS_WINDOWS and support.MACOS (GH-7800)" (GH-7919)
937ee9e
methane commentedon Feb 24, 2019
New changeset 3b0abb0 by Inada Naoki (Giampaolo Rodola) in branch 'master':
bpo-33671: allow setting shutil.copyfile() bufsize globally (GH-12016)
3b0abb0
vstinner commentedon Feb 25, 2019
shutil.COPY_BUFSIZE isn't documented. Is it a deliberate choice?
https://docs.python.org/dev/library/shutil.html
giampaolo commentedon Feb 25, 2019
Yes, it's deliberate, see PR-12016.
vstinner commentedon Feb 25, 2019
"I decided not to document
shutil.COPY_BUFSIZEbecause I consider it a corner case."Ok. I have no opinion on that, I just wanted to ask the question :-)
merwok commentedon Jul 31, 2021
New changeset b08c48e by Anthony Sottile in branch 'main':
bpo-33671 fix orphaned comment in shutil.copyfileobj (GH-27516)
b08c48e