読者です 読者をやめる 読者になる 読者になる

十分に物理メモリを搭載しているにもかかわらずスワップアウトが発生する理由

Vista

多くの人々は,Windows OS でのスワップアウトを「メモリが足りなくなったときの緊急回避」と考えているようです.実際,緊急退避的なスワップアウトも存在しますが,PC の搭載メモリが増えてきた現在では,しかし,もっと別の形でのスワップアウトの方が頻繁に起きるようになってきています.ここでは,より現実的なスワップアウトの姿を見てみることにしましょう.

ある想像上のプログラムを考えます.そのプログラムは,300 MB のヒープを確保し,同時に 300 MB 程度のファイルのあちこちにランダムアクセスを繰り返すとします.
Windows は,このアプリケーションを円滑に動作させるために,どのように物理メモリを提供するのでしょうか?

アプリケーションが,ヒープに対するランダムアクセスのみを行い,ファイルアクセスはほとんど行わない場合

この場合,300 MB の物理メモリをヒープのために維持し続け,アクセスが少ないファイルキャッシュは徐々に縮小されていきます(もちろんメモリが余っていれば使用頻度が低くても生き残る可能性はあります).
このような環境では,そのアプリケーション用として物理メモリに 300 MB の余裕ができるまではメモリ投資効果は高いでしょうが,それ以上に物理メモリに投資してもスループットは改善しないでしょう.

アプリケーションが,ファイルアクセスを頻繁に行い,ヒープに対するアクセスをほとんど行わない場合

この場合,300 MB の物理メモリをディスクキャッシュのために維持し続け,アクセスが少ないヒープは徐々にページファイルに退避されていきます(もちろんメモリが余っていれば使用頻度が低くても生き残る可能性はあります).
この退避作業は,順を追って行われます.
まず,物理メモリ上に存在するヒープの内容をページファイルに書き写します.この作業は,実際にメモリが逼迫する以前に“投機的に”行われることに意味があります.書き写しが完了すると,物理メモリとページファイル両方に,同じヒープ内容が存在することになります.これにより,物理メモリ上に存在するヒープの内容は,任意のタイミングで破棄できるようになります.この段階で,物理メモリ上のヒープは,ページファイル内容の“ファイルキャッシュ”と等価です.
後は他のファイルキャッシュと同じです.もっと別の内容を物理メモリ上にキャッシュした方が良いと OS が判断するタイミングで,ヒープを“キャッシュ”していた物理メモリは,別の用途に転用されます.
この時点で,いわゆる“スワップアウト”が完了します.
また,このような環境では,そのアプリケーション用として物理メモリに 300 MB の余裕ができるまではメモリ投資効果は高いでしょうが,それ以上に物理メモリに投資してもスループットは改善しないでしょう.
十分なサイズのディスクキャッシュが確保できる環境では,定常状態において,HDD のアクセスの影響を取り除くことができます.

アプリケーションが,ヒープに対するランダムアクセスも,ファイルアクセスも,どちらも頻繁に行う場合

この場合,300 MB の物理メモリをヒープのために維持し続け,同時に 300 MB の物理メモリをディスクキャッシュのために維持し続けるのがベストです(もちろんメモリが足りなければ,この限りではありません).
このような環境では,そのアプリケーション用として物理メモリに 600 MB の余裕ができるまではメモリ投資効果は高いでしょうが,それ以上に物理メモリに投資してもスループットは改善しないでしょう.

まとめ 1 : 十分に物理メモリを搭載しているにもかかわらずスワップアウトが発生する理由

Windows OS では,「ファイルキャッシュから使用頻度の低いキャッシュ内容を削除」するのと同じ感覚で,「プログラムが確保したメモリの内容をスワップアウト」しています.より正確に言えば,両者を共通のアルゴリズムで扱えるよう,意図的にメモリマネージャが実装されています.
別の言い方をしてみましょう.
我々が C/C++/C# などの言語からアクセスしていると思っているところの物理メモリとは,実は,仮想的なメモリ空間の一部が物理メモリにキャッシュされたもの,と考えることもできます.つまり,最近アクセスしたアドレス領域は物理メモリにキャッシュされていますし,しばらくアクセスしないアドレス領域は OS が不要と判断してキャッシュから削除して (ページファイルに書き戻して) しまうわけです.
そしてこれが,Windows で,十分に物理メモリを搭載しているにもかかわらず,なぜかヒープのスワップアウトが発生する,という理由でもあります.
端的に言えば,malloc で確保したメモリは,物理メモリ上の存在意義をかけ,ディスクキャッシュと常に戦っています.そして,その戦いに敗れれば,ページファイルに送られてしまうというわけです.十分に物理メモリを搭載したはずなのに,プログラムがスワップアウトされていたときには,ヒープの方が「ヒット率」が低いというのが OS 判断だったとお考えください.

まとめ 2 : 搭載メモリ量を超えるようなファイルマッピングが邪悪な理由 (あるいは 64 bit OS に対する一部の幻想に対する回答)

物理メモリにキャッシュ可能なサイズは,当たり前ですが,PC に搭載された物理メモリのサイズを超えることができません.
確かに 64 bit OS では,巨大なファイルをまるごと仮想アドレス空間にマップすることは可能です.しかし,数十 GB のファイルをメモリマップしても,同時にキャッシュ可能なサイズは搭載メモリ量を超えられないことに違いはありません.搭載メモリ量を超えるような巨大なファイルをメモリマップして,そのあちこちにランダムアクセスするようなプログラムは,非常にパフォーマンスの悪いものになるでしょう.
64 bit OS の導入は,目前に迫ったアドレス空間の上限と,搭載可能メモリ量の上限の問題に対する解決策にはなりますが,搭載メモリ量を超えるランダムアクセスを実用的にするような魔法の薬ではないのです.