SuperFetch

TechEd 2006 Yokohama や CEDEC 2006 で私に捕まっちゃった方は「Windows Vista だと Visual Studio 2005 の起動がこんなに速いですよー」というのを散々見せられたかと思いますが,今回はそのあたりについて.
テスト環境は以下の通り.

この環境,Vista 用にメモリを増設したこともあって,起動直後にメモリが足りないということはもちろんありません.ログイン直後のコミットチャージはだいたい 500 MB から 600 MB です.
おもしろいのはここからです.起動後も HDD へのアクセスは止まらず,タスクマネージャを見てみると「パフォーマンス」タブに表示される「キャッシュ済み」の項目が増え続け,それに応じて「空きメモリ」がどんどん減少していきます.そして,20 分程度かけて「キャッシュ済み」が約 1.5 GB に,「空きメモリ」が 10 〜 数十 MB になったところで変化が止まりました*1.以下は,その状態のタスクマネージャの様子です.

実際この状態では Visual Studio 2005 の起動は非常に軽快になっていました.以前に起動したときにも何度も Visual Studio 2005 を使用してきたこの環境では,今回の起動後も使用される可能性が高いと判断され,SuperFetch によって Visual Studio 起動時に読み込まれるファイルの多くがメモリ上に事前読み込みされているものと予想されます.実際これを確かめてみましょう.



Windows Vista では,パフォーマンスカウンタに物理ページの状態ごとの統計情報を示すカウンタが追加され,従来カーネルメモリを参照しなければ分からなかったスタンバイリストのサイズ等が分かるようになっています*2.いくつかおもしろそうなカウンタを並べてみましたが,特に Standby Cache に関する 3 つのカウンタが興味を引きます.

これらはいわゆるスタンバイリストのサイズを現すカウンタだと考えられますが,『インサイド Microsoft Windows 第4版〈上〉』(asin:4891004738) にはスタンバイリストに優先度分けがあるという記述は見あたらなかったことからも,この優先度分けが Windows Vista で導入されたものと予想されます.恐らく SuperFetch や ReadyBoost といった新機能と含めて,メモリマネージャにそれなりに手を入れたのでしょう*3
さて,実際このスタンバイリストにアプリケーション起動時のファイルが先読みされていることを確認してみましょう.
Windows SDK をインストールすることで最新の Debugging Tools for Windows も導入されますので,WinDbg を使用してカーネル情報を見てみることにします.そのまえにシンボルサーバの設定をしておきましょう.私はいつも C:\SymbolCache というフォルダを作って,ここにダウンロードしたシンボルを保存することにしているので,環境変数 _NT_SYMBOL_PATH は次のようになります*4

srv*C:\SymbolCache*http://msdl.microsoft.com/download/symbols

設定後 WinDbg を起動し,File → Kernel Debug → Local でローカルデバッグが開始します.もちろん「管理者として実行」しておかないとダメです.ちゃんと起動すればこういう画面が見えるはず (フォントは変えてあります).

無事起動したところで,『インサイド Microsoft Windows 第4版〈上〉』第 7 章,7.11 ページフレーム番号 (PFN) データベース,「実験 PFN データベースを調べる」にならって,各種ページリストの詳細を見てみましょう.コマンドは次の通りです.

!memusage

まず,PFN データベースの読み込みが完了すると,各種ページリストのサイズが表示されます.先ほどパフォーマンスカウンタに表示されていた,スタンバイリストの優先度分けはここでは分からないようですね.

次に PFN データベースの中身の解析が始まります.メモリ搭載量が多いとしばらくかかるので待ちましょう.
解析が終了すると,次のような画面から始まる長いリストが表示されます.


このリストをよく眺めると,例えば "ドライブラシ.8bf" というファイルが 68 ページほどスタンバイリストに格納されており,同様に "ツールパレット.aip" は 40 ページ分のスタンバイリストに格納されていることが分かります.これらのファイルは Adobe Illustrator CS の起動時に読み込まれるプラグインファイルですが,確かに以前 OS を起動したときに何度か Illustrator を使用しています*5.しかし,今回 OS を起動してからは一度も Illustrator CS を起動していません.よって,これらは SuperFetch によって事前ロードされ,スタンバイリストで待機しているファイルだろう,ということになるわけです.



さて,ここまでくれば ITpro の以下の記事の印象も少しは変わってくるかもしれません.

「Windows Vistaでは,シャットダウンよりもスリープを使ってほしい。Vistaロゴのあるマシンなら,スリープ状態から2秒で復帰できる」---マイクロソフトWindows本部の中里倫明シニアテクニカルエバンジェリストは,9月4日に開催したプレス向け説明会でこう強調した。

中里氏の意図がどこにあったかは別にしても,この Thinkpad T60 は OS 起動後 20 分以上かけて合計 1.5 GB ものファイル群を事前ロードすることと,シャットダウンによってその 20 分以上の事前作業が全て無駄になってしまうことは確かです.このようなデメリットを考えると,確かにシャットダウンは避けたいという気もしてきます.



今回調べてみて,Windows XP のキャッシュ戦略と Windows Vista のそれは随分異なるという印象を受けました.具体的には,Windows Vista では余剰メモリを「アプリケーションの起動時間短縮」につぎ込むという強い意志が感じられたように思います.確かに数 GB のメモリに現実に手に届くようになってきた現在では,この戦略は有効かもしれません.
一方で,いくつか疑問も残ります.例えば 8GB 近いメモリを搭載してしまうと,この環境では起動後 1 時間近くディスクアクセスが続くのか気になるところですが,これはテスト環境が用意できなかったため不明です.もし手元にそういう環境をお持ちの方は,そういった点に注意してみて,何か問題がありそうであれば早めにフィードバックを入れていただけると,後で多くの人が助かることかと思います.実際,過去のキャッシュ戦略の変遷が,スケーラビリティとの戦いであったことを考えると,今回の戦略が 10 GB や 20 GB の環境で破綻しないかどうかは注意しておく必要があるでしょう.
また,ReadyBoost の併用効果についても興味があるところです.パフォーマンス・カウンタの値からは ReadyBoost は圧縮も行っているようで,手元の環境では圧縮比は約 1 : 1.5 でした.4 GB クラスの高速シリコンストレージを使用すれば,約 6 GB の高速ストレージが手に入ることになるわけですが,これによって SuperFetch に要するディスクアクセスが減少するかどうかなど,時間が取れればまたテストしてみたいと思います.
最後に,アプリケーション開発者としても,OS レベルでのこういった最適化の存在は意識しておきたいところです.アプリケーションの起動時間というのは,比較的ユーザのクレーム対象になりやすい部分です.そのため,スプラッシュウィンドウを表示したり,事前にロードしておくプロセスを常駐させたりといったさまざまな工夫が行われてきました.しかし,今回 Windows Vista で OS による事前ロードが明確に推進されたことから,自作常駐プロセスによるプリロード効果はある程度減少すると考えられます.それよりも,起動時にハードページフォルトが起きないと仮定して,起動処理の並列化を推し進める方が効果が大きいかもしれません.
以前は,アプリケーション起動時間はほとんどの場合ディスクで起動速度が決まってしまい,並列化といった CPU レベルでの最適化効果が薄かったと考えられます.しかし Windows Vista では,(メモリを十分搭載し,事前にある程度寝かせた場合は) アプリケーション起動時の CPU 処理が多いアプリケーションほど起動が遅く見える,という風に変化してくるかもしれませんね.


参考資料

*1:この挙動は稼働状況によって変化しうることに注意してください.実際,バッテリー駆動時にテストすると,「キャッシュ済み」サイズの増加は 600 MB 程度で停止しました.

*2:他にも ReadyBoost に関するカウンタや,Video Scheduler といった興味深いカウンタが追加されています

*3:このあたりに関係してか,PFN データベース構造体のサイズも 4 byte 程増えているようですね.

*4:そういえば一般ユーザのままで自分の環境変数を設定するのどうやるんだろう?

*5:XAML とのコンバートで遊んだり