きっかけ
10年ほど前に納品したソフトのお客様要望として、ソフト内で実行している、8Mバイト程度の複数ファイル(100程度)のコピー処理を高速にしてほしいというものがありました。(未だに使用していただいてありがたいことです)
実際にソフトでやっている処理は、Win32APIのCopyFile()一発でディスクドライブをまたいだファイルコピーを繰り返す、というものでした。
お客様所有のPCにインストールして使用するソフトなので、そのときとった対応は、「RAID0で構成してみては?」とか「NVMeのSSDにしてみたら?」といったハードウェア更新のすすめ(ちょうどWindows11PCに更新するよってことでしたので)だったのですが、後々対応する必要のある案件と思いソフト側の対応準備を進めていました。
その対応準備の一つとして、ファイルコピーの高速化について調べてみることにしました。
ExtremeCopyを調べてみる
Windowsでのファイルコピー高速化ってどうやっているんだろうとgithubで調べてみると、ExtremeCopyというソフトが引っかかりました。処理自体はありがたいことにDLLでまとめられているので、早速組み込んで比較してみました。
Win32apiCopyFile: 2843msec
ExtremeCopy(sync): 25285msec
はて、困りました。Win32APIのCopyFileをそのまま使う従来処理の方がずっと速いじゃん。ExtremeCopyの中でやってる処理をみてみると、バッファメモリを介してReadFile/WriteFile、かな。非同期にすればブロックはしないけど、それだったら他にもやりようはあるし。
CopyFileの方はキャッシュに入れるだけであとの処理はWindowsOS任せなんだろうなと挙動を予測できます。
そこで更に調べてみると、OldNewThingのこちらがヒットしました。
CopyFileEx()までは知っていましたが、CopyFile2() (Windows8~) なんてものまでできてたのね。
でここで書かれている、CopyFile2を使用したCopyFileWithFlushに置き換えたときの速度を見てみることにします。
CopyFIleWithFlush(CopyFile2使用)
Win32apiCopyWithFlush: 62163msec
それなりの速度で安心しましたw
結局、今のソフトの仕様に基づけばファイルコピーの処理自体を敢えて変更する必要はない、という結論になりました。(試験で負荷が溜まったとき等の処理が問題になったら検討はしますが)