Pythonのshutil.copyが異常に遅い件。

前から気付いていて、Pythonも3.9になったので改善しているかしら?と試してみましたがやっぱり未だに異常に遅いようです。
なぜかこれはWindowsプラットフォームだけのようですが。

1GBのファイルをSSDの2台のドライブの間でコピーする速度を計測してみました。
1 Subprocess copy to dir 0.3177815
2 shutil.copyfile 5.799549600000001
3 shutil.copy to dir 6.2538441
4 shutil.copy to file 5.642608300000001
5 shutil.copyfileobj (16MB) 9.0621711
6 shutil.copyfileobj (128MB) 20.3517843
7 shutil.copyfileobj (-1) 21.7088837
8 copyFile to file (default) 9.210321199999996
9 copyFile to file (16MB) 8.914450500000001
すべて1GBのファイルを別のSSDドライブに10回コピーしたのに要した時間です。圧倒的にsubprocessが早いです。 1のsubprocessは、
for i in range(10):
    subprocess.run('cmd /c copy "{0}" {1} > nul'.format(fname, dest_dir), check=False)
    
というコードです。
2はshutil.copyfile()、3はコピー先にファイルを、4はコピー先にディレクトリを指定したshutil.copy()です。
5、6、7はそれぞれ、buffer_sizeに16MB、128MB、-1を指定したshutil.copyfileobj()です。-1の場合にはファイルを一度に全部読み込むだけのバッファを確保する、という説明がありましたので、計測してみました。
8と9は、Faster Python File CopyにあるcopyFile()を使用してみました。処理手的にはshutil.copyfileobj()を使っていますので、5と同程度になります。
Linuxなどの場合にはここまでの差は出ないようで、ほとんど1と同じ時間だということですが、shutil.copy()は"cmd /c copy"の約20倍の時間がかかっています。本来ならば外部コマンドを呼び出すオーバーヘッドなどを考えると、subprocessのほうが遅いはずなのですが、ことWindows上での大きいファイルのコピーに関してはsubprocessに軍配が上がるようです。

追記(2022年6月26日):
前から気づいてたんですが、ここに書いてなかったので追記しておきます。
Changed in version 3.8: Platform-specific fast-copy syscalls may be used internally in order to copy the file more efficiently. See Platform-dependent efficient copy operations section.

https://docs.python.org/3/library/shutil.htmlに記載されてますが、Python 3.8からコピーが劇的に速くなっています。

0 件のコメント:

コメントを投稿

Vimの補完プラグインをインストール。その4

Vimの補完プラグインをインストール。その3 で、 ddc-tabnine が使えそうです、などと書いたのですが、早速やってみました。 まず、tabnineのバイナリを用意しないといけません。がどうにもTabNineのサイトがわかりにくいので、 tabnine-nvim にあるダ...