readfile(),writefile() などのファイル入出力のAPIで
確保するバッファーサイズは、どのようなサイズがいいのでしょうか?
コピーを高速化したい場合は、可能な限り大きく確保すればよいのでしょうか?
開発環境について書かいて下さい。
開発環境がわからないと適切な回答が書けないことがあります。
OSのバージョン、コンパイラーのバージョン(VC 6.0 など)、
MFC を使う/使わない、SDKのみ、managed なC++など
>確保するバッファーサイズは、どのようなサイズがいいのでしょうか?
「必要なだけ確保する」が私の考えです。
ファイルを全部読み込むことが可能な場合は全部読み込むこともあります。
一行毎に処理をする場合で、一行の長さの上限が決まっている場合はその
上限にするだろうし。処理によって違ってくると思いますけど、どうでしょう?
>コピーを高速化したい場合は、可能な限り大きく確保すればよいのでしょうか?
それもどうでしょう。コピー対象が小さい場合は可能な限り大きくすると
使いもしない記憶領域を確保することになるような気がします。
なので状況に応じて領域の確保の考え方はいろいろだと思います。
開発環境は、VC++2005,2008,2010 MFC またはSDKのみの汎用的です。
コピー対象とするファイルは、動画ファイルなどの数GBの大型バイナリーファイルで、
windowsで、ドロップしてコピーすると、残り200分などと表示させるサイズの
ものを想定してください。よろしくお願いします。
>動画ファイルなどの数GBの大型バイナリーファイルで、
>windowsで、ドロップしてコピーすると、残り200分などと表示させるサイズの
>ものを想定してください。
自分のアプリケーションだけが動く場合なら確保できる上限まで取ってしまうことも
問題ないでしょう
ただ、主記憶の容量以上に確保してもWindows は(32/64共に)仮想記憶なので、
ページングの対象が増えるだけですから、コピーの速度が早くなる方向に効くとは
思えません。
もっとも、ちょこまか読書きするよりはドンと大きく読書きする方がコピー時間
が短くなるとは思います。4Gバイト確保したからといって主記憶で 4G バイト
確保できる保証がない以上(Win32 はアプリケーションの記憶空間は 2G もしくは
3G が上限です)やたらでかくとってもコピー速度にとって意味があるかどうか
疑問です。
こういう効率の問題は実際に試してみるのが一番です。
まあ今でもメモリ実装量 512MB のマシンもいっぱいあるわけで。
コピー用のバッファに実記憶より大きなサイズを取得するなど無意味。
バッファサイズとしてはディスクのセクタサイズの整数倍がいいだろうし、
いまどき AFT な 4KB セクタサイズのディスクも普及しているし、
64KB とか 128KB 程度に抑えておくのが良いんではないかな・・・と。
ちなみに CopyFileEx を使わないのはなぜ?
ReadFile + WriteFile だけだとタイムスタンプなど副次情報はコピーされないし
代替ストリームもコピーされない。
残りバイト数なんかも自動でわかるし手作りするよりずっといいと思うが。
共通関数的な物を作成しようとしているのであれば、
tetrapodさんが書かれているようにCopyFileExを使わないのはなぜと言う話になるかと。
使えない理由があるのであれば、それも提示しておかないと話が繋がりません。
既に皆さんが書かれているようにとにかく大きくすれば良いという話ではありません。
あと、ユーザーが使っている他のアプリへの影響などを考えると結果的に傍迷惑な
関数になりかねません。実際の話、こうすれば良いと言う銀の弾丸はありませんから
使用される環境に合わせてチューニングするか、共通関数と言う位置付けなら
なるべく効率が良くて利用環境を縛らない容量を自分で探ると言う話になると思います。
うーーん、
コピーの高速化をしたいのなら、データーの欠落を防ぎながらマルチタスク処理
を行なう。
だと思うのですが、どうでしょうか?
WiNDOW7になって、64ビット版を使う人が増えているかに思います。
今は、メモリーの確保をして、高速化を図る時ではないと思います。
ありがとうございます。
readfile(),writefile()を使用したい理由は、「**%完了」など、途中で進行状況を把握
したいためです。
マルチスレットにするのは、直観的ですが、処理速度速度を考えると、CPUの処理より
も、ハードディスクの書込速度のほうが影響が大きそうなので、どうかなとも思います
が、いかがでしょう。
>readfile(),writefile()を使用したい理由は、「**%完了」など、途中で進行状況を把握
>したいためです。
で、皆さんが掲示しているCopyFileEx()は調べてもいない…ということでしょうか?
CopyFileEx()でコールバック関数が指定できますが、そこに
・バイト単位の総ファイルサイズ
・転送された総バイト数
とか渡されますが…。
> マルチスレットにするのは、直観的ですが、処理速度速度を考えると、
> CPUの処理よりも、ハードディスクの書込速度のほうが影響が大きそうなので、
> どうかなとも思います
> が、いかがでしょう。
コピーした後、すぐに何か処理があるというなら、
最終書き込みは後にしてメモリーに書き込んでおく。
というのは分かりますが、GB単位あるとなるとそれも現実的でないですね。
ハードディスクの速度の問題なら、SSD限定にしてもらうなど、考えれば
手段もあるのでは?
FireFileCopyやFastCopyなどフリーで高速コピーできるツールもあるみたいです。
実際に使って見ることもいいと思います。
CopyFileExは、処理自体はOS任せですから
質問者の意図にそぐあないですよね。。
セクタサイズや、API発行毎の処理のトロさに左右されますから
数K~数MB程度の間で実験してみるのが一番かと。
あとFastCopyはソースも公開されているので
参考にしてみてはどうでしょうか。
処理がOS任せであったとしても性能的に十分で機能的にもOKなら
選択肢としてはありだと思いますよ。
実際に試してみて自分の要件に合わなければ、候補から外せば良いだけですし。
質問時の内容に関しても漠然としているのでそもそもCopyFileExでは駄目なのかが
わかりません。
既に試していて性能的にだめという結論が出ているなら話は別ですが、
はっきり結論が出ていないのであれば、試してみる必要はあると思いますよ。
性能的、機能的に満足できないのであれば、自作するのも一つの方法なので
その場合は既に紹介されているようなアプリのソースを参考にさせてもらうとか
しても良いと思います。
汎用的に早くて利用環境を選ばないような物を目標にするのであれば、
かなり試行錯誤が必要そうですね。
試してみるのも面白そうではありますけれど。
CopyFileExのサンプルが載ってるHP↓
http://d.hatena.ne.jp/s-kita/20100619/1276914572
リンク先にサンプルコードと実行結果(コピー途中のサイズ取得)が載っています。
遅くなりましたが、この件は重要な考慮点があります。
以前に試してみた結果、
1) バッファを1Byte → まじで遅い
2) バッファを4KByte → エクスプローラ並みの速さ
3) バッファを100MByte → 4KByteと大して変わらない
そして、重要なのはネットワークを介してファイルを読み書きする場合です。
あまりバッファサイズを大きくすると、タイムアウトが発生するようで、
読み書きに失敗します。
再試行すると、どういう原理なのか成功しますが、タイムアウトを回避するの
が大変です。
いろいろ試しましたが、数KByte程度が良さそうです。
ネットワーク越しになると実は話が変わってくるって部分は
見落としがちかもしれませんね。
実際には別のPC上のパスを指定されるだけなので同じインターフェイスで
ローカルのコピーもネットワーク越しのコピーも出来てしまいます。
内部的にネットワーク越しでないかどうかのチェックでもしない限りは
同じロジックで動いてしまいますからね。
bunさんの指摘も考慮に入れると同じロジックで行くなら
バッファサイズをむやみやたらと大きくしても処理スピードは
上がらないと言う事になりますね。