TrickDiary このページをアンテナに追加 RSSフィード Twitter

2008-04-30

[][] 大容量ファイルI/Oの効率について 其の弐

id:NyaRuRu さんからコメントでご指摘を頂き、再計測したのですが下のような結果が得られました。

f:id:wraith13:20080430231453p:image

FILE_FLAG_NO_BUFFERING 指定のない ReadFile() -赤線-
リニアにアクセス速度が低下していく。FILE_FLAG_NO_BUFFERING の指定がある場合にはリニアな速度低下の傾向は見られないことから、大容量ファイルの I/O というかリードを行うことに対して WindowsI/O バッファリングアルゴリズムにパフォーマンスバグがあると思われる。FILE_FLAG_NO_BUFFERING を指定すれば回避できるとはいえ、コンシューマ市場向けにもTBクラスのストレージが出回ってる昨今、これは致命的な問題だと思う。
FILE_FLAG_NO_BUFFERING 指定のある ReadFile() -緑線-
2GiB の読み込みに概ね12-13秒台の高速でコンスタントなアクセス速度を誇る。(・∀・)イイ!! FILE_FLAG_NO_BUFFERING を出力ファイルに対して使用するとエラーになることから、入力ファイルに対しても開発・テスト環境ではエラーが起きなくてもその他の環境やシチュエーションによってはエラーになったりしたら嫌だなと避けてたんですが、これなら例えエラーになるケースがあろうとも使わざるを得ないですね。念のためにネットワーク越し、CD-RFATUSB メモリからの読み込みを試してみましたがエラーにはならないですね。id:NyaRuRu さん、ありがとう!
FILE_FLAG_NO_BUFFERING 指定のある ファイルマッピング -青線-
2GiB の読み込みに概ね14秒台の区間と概ね20秒台の区間が存在しそのアクセス速度は時系列に矩形波を描く。矩形波ってなんでやねん? マジで意味がわからん。

あと、既にファイルI/Oをそれ専用のスレッドで行うようにしている関係もあり、非同期がいいって話でしたが今回は試してないし、ETWによる測定も結局やってないです。

NyaRuRuNyaRuRu 2008/05/01 08:01 >FILE_FLAG_NO_BUFFERING を出力ファイルに対して使用するとエラーになる

このあたりは大丈夫ですか?
http://msdn.microsoft.com/ja-jp/library/cc429198.aspx
>>このフラグを指定した場合、アプリケーションは次の各条件を満たさなければなりません。
>>•ファイルアクセスの開始オフセットを、ボリュームのセクタサイズの整数倍にしなければなりません。
>>•ファイルアクセスのバイト数を、ボリュームのセクタサイズの整数倍にしなければなりません。たとえば、セクタサイズが 512 バイトの場合、512 バイト、1,024 バイト、2,048 バイトの読み書きはできますが、335 バイト、981 バイト、7,171 バイトなどの読み書きはできません。
>>•読み書き操作用のバッファのアドレス(メモリ内のアドレス)を、ボリュームのセクタサイズの整数倍に整列(セクタ整列)させなければなりません。ディスクによっては、この要件を満たせないこともあります。

FILE_FLAG_NO_BUFFERING + ファイルマッピング は意味があるのかどうかよく分からないです.

デフォルトの,つまり FILE_FLAG_NO_BUFFERING を使用しない ReadFile がどういう動作かというと,システムキャッシュビュー領域に該当領域を mmap して,そこから渡されたバッファに memcpy という動作をしています.(「インサイド Windows 第4版 11.2 キャッシュ仮想メモリ管理」)
この領域はそれ程大きくないので,超巨大ファイルをシーケンシャルにアクセスするときは,mmap の張り替えを一定ペースで行う必要があり,これが CPU 負荷を高めることになります.
また,2 回コピーするため,10 GiB のデータを読むのに,20 GiB のメモリコピーが必要になります.
一方で,Windows の先読みスレッドとはそこそこ相性がよいです.先読みスレッドが先回りしてファイルアクセスを行ってくれるため,目的のプロセスが ReadFile しに行ったときは既にページインしているメモリから memcpy するだけで OK というわけです.ただしこれがうまく機能するのは,ディスク I/O よりも読み取ったデータ処理コストの方が高いときです.生のディスク I/O 律速の場合は先読みスレッドがあろうがなかろうが関係ないですからね.

一方,FILE_FLAG_NO_BUFFERING 指定のある ReadFile では,プログラムから渡されたメモリ領域に直接書き込まれるため,mmap コストや memcpy コストがかかりません.

この辺の議論とかモチベーションは Mark Russinovich 先生のファイルコピー記事を注意深く読んでいると何となく分かるかと.
http://d.hatena.ne.jp/NyaRuRu/20080228/p1

wraith13wraith13 2008/05/01 23:47 >このあたりは大丈夫ですか?

見事にそれですね。入力の方はファイルマッピングに対応していた関係上、SYSTEM_INFO::dwAllocationGranularity の値(64KiB)でアライメントしていたのでエラーにならなかっただけですね。
てか、よくみるとなにげに「ディスクによっては、この要件を満たせないこともあります。」とか嫌なことがハッキリと書いてありますね。(’A`) 
入力か、出力か、に関わらず、うまくいかない場合は FILE_FLAG_NO_BUFFERING を指定しないで開き直すようなエラーハンドリングをする必要がありそうですね。

あと、エラーにならない場合でも FILE_FLAG_NO_BUFFERING 指定を伴うファイル出力は最後のブロックをどう処理するかがまた悩みものですね。SetFileValidData() を使うには SE_MANAGE_VOLUME_NAME 権限が必要だし。


>デフォルトの,つまり FILE_FLAG_NO_BUFFERING を使用しない ReadFile がどういう動作かというと,...これが CPU 負荷を高めることになります.

んー、でも、いくらなんでも「バッファ/キャッシュを使用している」ってだけの理由でリニアなパフォーマンス劣化を起こすって酷くね?
これ 100GiB だから末尾と先頭の速度比がまだ約3倍で済んでるけど、同じ環境下の前提で 1000GiB のデータとかだったらただでさえデータのボリュームがでかいのに末尾のほうでは単純計算で約21倍の時間がかかることになるし、なんの為のバッファ/キャッシュなんだか。

...ん、待てよ? ひょっとしたら真犯人はアンチウィルスソフトやバックアップソフト(FileSystemFilterDriverとかよく使われてるし)とかそういう可能性はなきにしも...時間がかかってもこのまわりの疑いは確実に晴らしておいたほうがいいですね。


>FILE_FLAG_NO_BUFFERING + ファイルマッピング は意味があるのかどうかよく分からないです.

FILE_FLAG_NO_BUFFERING の指定がないと上のグラフの青線と赤線を組み合わせたようなアクセス速度の変化を起こします。おそらく青線の矩形が消失するようなマクロな視点から見れば赤線とほぼ重なるとハズです。


>http://d.hatena.ne.jp/NyaRuRu/20080228/p1

情報いろいろありがとです。


んー、また、時間のあるときに(環境非依存高速)ファイルアクセスモジュールとか作ってみたいですね。
てか、仕事上で同様のものを既に作ってるわけだけど、試行錯誤を繰り返しながらだからとんでもないコードになっちゃってるし。
もっと情報収集しっかりやってから設計し直したい。

NyaRuRuNyaRuRu 2008/05/02 07:06 >単純計算で約21倍の時間がかかることになるし

あるいは Microsoft 側が想定してなかったスケールということで,次期 OS でこっそり直ってたりとかの可能性もありますな.

wraith13wraith13 2008/05/02 21:24 >ひょっとしたら真犯人は...

調べた見ましたが、アンチウィルスソフトは入ってなかったし、WinObj で確認してもサートパティの FilterDriver は入ってませんでした。あと、HDD のドライバも調べてみたけど、MS純正のドライバのみ。とりあえず問題を引き起こしてる箇所がMSの責任範囲内ってのは堅そうですね。また時間のあるときにでも全然違う環境で追試しておきます。


>あるいは Microsoft 側が想定してなかったスケールということで,次期 OS でこっそり直ってたりとかの可能性もありますな.

確かに今回、問題になってる環境って大容量ファイルを高速に処理するために RAID0 を組んでることもありファイルアクセス速度が高速な故に影響がでかいですが、ベースとなるファイルアクセス速度が遅ければ速度低下の比率がここまで酷いことにはならないでしょうし許容範囲になり得ますね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

リンク元