The fastest version without re-optimizing the code I have with the following code:
class CTError(Exception): def __init__(self, errors): self.errors = errors try: O_BINARY = os.O_BINARY except: O_BINARY = 0 READ_FLAGS = os.O_RDONLY | O_BINARY WRITE_FLAGS = os.O_WRONLY | os.O_CREAT | os.O_TRUNC | O_BINARY BUFFER_SIZE = 128*1024 def copyfile(src, dst): try: fin = os.open(src, READ_FLAGS) stat = os.fstat(fin) fout = os.open(dst, WRITE_FLAGS, stat.st_mode) for x in iter(lambda: os.read(fin, BUFFER_SIZE), ""): os.write(fout, x) finally: try: os.close(fin) except: pass try: os.close(fout) except: pass def copytree(src, dst, symlinks=False, ignore=[]): names = os.listdir(src) if not os.path.exists(dst): os.makedirs(dst) errors = [] for name in names: if name in ignore: continue srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if symlinks and os.path.islink(srcname): linkto = os.readlink(srcname) os.symlink(linkto, dstname) elif os.path.isdir(srcname): copytree(srcname, dstname, symlinks, ignore) else: copyfile(srcname, dstname)
This code is a bit slower than native linux "cp -rf".
Compared to shutil, the gain for local storage up to tmfps is about 2x-3x and about 6x for NFS for local storage.
After profiling, I noticed that shutil.copy does a lot of fstat syscals, which are pretty heavyweight. If you want to optimize further, I would suggest making one fstat for src and reusing the values. Honestly, I didn’t go any further, since I got almost the same numbers as my own linux copy tool, and optimization for a few milliseconds hundrends was not my goal.
source share