記事紹介: Inside Vista SP1 File Copy Improvements (2)

id:NyaRuRu:20080228:p1 の続きですが,うーむ,前回記事は色々と失敗だなぁ.
やっぱり記事紹介か,もうちょっと突っ込んで解説するかどっちか一方に徹した方が良かったですね.混ぜて書いたのは失敗でした.
いずれにしても公開するまでに少し時間をおいて読み直すべきでした.とりあえず切りが悪いので記事後半の紹介を先に済ませましょう.色々考えるべきことについてはまた次のエントリで.今回は基本的に記事に書かれている内容そのままの紹介 (のはず) です.

Vista RTM 版のコピーエンジンについて

  • Non-cached I/O と Large I/O の併用だよ.でも小さいファイルについては Cached I/O を使うよ.
  • 新しいコピーエンジンはリモートからローカルへの転送でローカルシステムのキャッシュメモリを消費しないよ.
  • キャッシュマネージャがビューを前から後ろに切り替えていくメモリマップコストも無くなったよ.
  • 初期の Vista のキャッシュマネージャは Large I/O の取り扱いが効率よくなかったのも non-cached を選んだ (cached I/O を使わなかった) 理由だよ.
  • でも Large I/O は,正確な見積もり時間をユーザに提供する点でも難しいよ.
    • なぜなら計測点が少なくなっちゃうから.
    • 他にも non-cached I/O では多数の小さなファイルをコピーするとき,HDD のヘッドが常にディスク上を,最初はコピー元,次はコピー先,次はコピー元,という感じにあちこち移動するという問題が見つかったよ
  • 多くの分析とベンチマークとチューニングの後,製品開発チームはサイズが 256 KB 以下のファイルには Cached-IO を利用するというアルゴリズムを実装したよ.
    • 256 KB より大きなファイルについては,コピーエンジン内部の数表によって一度に行う Non-Cached I/O の回数とサイズを決めるよ.
    • この回数は,2 MB より小さいファイルの 2 回,8 MB より大きいファイルの 8 回まで広がっているよ.
    • サイズの方は,1 MB より小さいファイルは 1 MB,それ以上 2 MB 以下のファイルは 2 MB,それより大きなファイルは全部 2 MB だよ.
    • 例えば 16 MB のファイルをコピーするとき,コピーエンジンは 8 回の 2 MB 非同期 non-cached 読み込みを使ってコピー元からデータを読み出して,I/O が完了するのを待ってから,8 回の 2 MB 非同期 non-cached 書き込みを使ってコピー先にデータを書き出すよ.以下例.

Vista RTM 実装の何が問題だったか? (1) / シーケンシャル I/O がランダム I/O になっちゃうことがある

  • メリットもあったけどデメリットもあったよ.
  • 非同期 I/O を採用したせいで,ネットワークコピーの書き込み動作の順序が変わってしまうことがあったよ.
    • 元々シーケンシャルだったはずの書き込みが,非同期 I/O のせいで Out-of-order に実行されている例.

    • 表を見ると 327,680 から 458,752 にジャンプしてるよね.こういうことやるとディスクヘッドはシークしなきゃいけないし,NTFS はスキップした部分に 0 を書き込む無駄な作業が必要になるんだ*1.ほら,393,216 からの書き込みが 2 回おきてるよね.

    • 上のイベントのスタックを見ると,NTFS が Cache Manager の CcZeroData を呼び出して,スキップした部分に 0 を書き込んでいるのが分かるよ.

Vista RTM 実装の何が問題だったか? (2) / 実はキャッシュは思ったほど無駄でもなかった

  • より大きな問題は,ファイル共有シナリオで non-cached I/O を使う場合だよ.
  • もしファイルの集まりを共有フォルダにコピーしたとき,その共有フォルダが例えばウェブサイトのコンテンツフォルダだったりする場合を考えるよ.(non-cached I/O でコピーされた場合は) 最初にそのファイルにウェブアクセスがあったとき,ウェブサーバは必ずディスクからファイルを読み込まないといけないね.
  • これは明らかにサーバでの問題だけど,でもほとんどのコピー作業はむしろクライアントシステムでのファイル共有シナリオの方だよね.
    • なぜってデスクトップに新しいファイルが現れると,デスクトップサーチのインデックス作成が始まって,アンチウィルス/アンチスパイウェアがスキャンを始めて,Explorer は親フォルダのフォルダアイコンに表示するサムネイルの作成を始めるんだ.

Vista RTM 実装の何が問題だったか? (3) / コピー終了の定義の問題

  • 最大の欠点は,もしかしたら,多くの Vista ユーザが不満を述べているように,サイズ 256 MB から何 MB の間のファイルを大量にコピーするときのものかもしれないよ.Windows XP に比べて体感速度がとてもとても悪化しうるからね.
  • 以前の,cached I/O を使うアルゴリズムは,Explorer がメモリ上にファイルを書き込み終わった時点でダイアログが閉じていたて,Cache Manager の書き込みスレッドが全部ファイルを書き出すのはその後しばらく経ってからだね.
  • でも Vista RTM 版の non-cached な実装では,全ての書き込みが完全に完了するまで待たされるんだ.さらに Vista RTM 版では,コピー時間の推定を始めるまで 12 秒待つのと,コピー時間の推定がコピースピードの揺らぎの影響を受けやすいことの両方が,遅いコピーへの不満をより悪化させたんだ.

Vista SP1 でどうしたか?

  • 一部の例外をのぞいてCached I/Oに戻したよ.
    • 例外はリモートファイルコピーの場合で,二重キャッシュ問題が起きないように通知メカニズムを作ったよ.そのときは Cache がバイパスされるよ.
  • せっかく Vista RTM 版で導入された Large I/O を,Vista RTM 版の Cache Manager がうまく活用していないという問題は解消されて,SP1 から Cache Manager はちゃんと Large I/O を使うようになったよ.
    • コピーされるファイルサイズに応じて,CopyFileEx は 128 KB から 1 MB のサイズの読み取りを 4 回ほど最初に発行するよ.これによって Cache Manager の先読みスレッドが大きな I/O で読み取りを開始するよ.
    • ローカルコピーでも,書き込みスレッドの効率が良くなるからメモリ圧力が改善されるよ.
    • Cache Manager は,アプリケーションが発行した読み込みサイズの 2 倍の読み込みを,Vista SP1 では最大 2 MB まで,Windows Server 2008 では 16 MB まで行うよ.
    • 同様に書き込みは Vista SP1 で最大 1 MB,Windows Server 2008 では 32 MB だよ.

  • Vista SP1 では,Windows Server 2003 との相性問題*2を考慮して SMB 1.0 の転送サイズを 32 KB/packet にしてあるよ.(Windows Server 2003 との通信だと?) Vista SP1 をあてることでファイルコピー速度が落ちるかも.特にレイテンシが大きいネットワーク環境だと.
  • Vista SP1 の Explorer は,コピー時間の推定を以前よりも,もっと速く終えるようにしたよ.



というわけで,記事の内容は概ねこんな感じ.
んで,次回はcached I/O VS non-cached I/O の裏側とか,ファイルコピーダイアログ終了後の遅延書き込みの確認の仕方とか,『インサイド Windows 第 4 版 下』の 11 章あたりを参考に考察してみたいと思います.
調べてみてびっくりしたんですが,XP と Vista SP1 で,ファイルコピー時のメモリの使い方の規模が全然違いますな.Vista での CcDirtyPageThreshold の拡大されっぷりがすごいです.詳しくは次回.

*1:そういえば CrystalDiskMark で最近似た話が [http://crystalmark.info/bbs/c-board.cgi?cmd=one;no=2268#2268:title=【2268】Re:CrystalDiskMark 2.1 リリースのお知らせ - CrystalMark 会議室]

*2:ファイルコピーでのファイルアクセスが Out-of-order になっちゃうのに惑わされて,Windows Server 2003 のキャッシュマネージャが大量にメモリを消費しちゃう