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

3 分ぐらいでわかる,Process Explorer による Windows Vista メモリ使用状況の調べ方

Vista

Commit Charge


まずこの辺に注目.
ここの数字は「メモリ確保がメモリ不足で失敗するかどうか」に関係しています.
試しに VirtualAlloc で MEM_COMMIT を行うと Current が増加して,MEM_DECOMMIT すると減少します.
Current が Limit を超えそうになるとメモリ不足で VirtualAlloc が失敗します. Limit の値はだいたい「搭載物理メモリ量」+「ページングファイルサイズ」 になっています.
つまり Commit Charge Current はメモリ確保時の「メモリ不足」の定義のためにあるようなカウンタです.物理メモリの 7 割がファイルキャッシュに使われているような状況でも,Current が Limit を超えそうになるとメモリ不足と扱われます.

Physical Memory


次に Physical Memory の欄に注目しましょう.Total は自明として,ややこしいのが Available と System Cache です.
Available は,後で示す Paging Lists の Zeroed と Free と Standby の合計値に他なりません.System Cache は歴史的にそう呼ばれているだけの変な合計値なので,無視しても良いでしょう.
Available にカウントされているメモリの内容は,その瞬間に内容を捨てても問題が起きないという特徴があります.つまり,その内容は全て 0 であったり,ファイル上のデータのコピーであったりというわけです.言い換えれば,Available の値が 0 に近づくと「すぐに利用できるメモリ」がどんどん減少していることを意味します.
また,Total から Available を引いたものは,現在アクティブに読み書きされている物理メモリ量とみなせます. Available をどれぐらいに保つかは基本的に OS が判断します.一般論としては,メモリアクセスの局所性を高めるように工夫されたプログラムであるほど,OS は Available の値を大きく保ちやすくなります.

Paging Lists


いよいよ本命.Paging Lists に注目です.

Zeroed
Available 扱いのメモリ領域のうち,内容がゼロクリア済みのメモリサイズ.色々な場面でゼロクリア済みメモリは重要なので,すぐに使用できるように一定量が確保してある.
Free
Available 扱いのメモリ領域のうち,完全に未使用領域のメモリサイズ.未使用というのは,メモリ上の内容に全く利用価値がないという意味での未使用.デコミット直後のメモリもここに送られる.溜めていても仕方がないので,大抵はすぐにゼロクリアされて Zeroed に移動する.
Modified
ディスク上のファイルまたはページングファイルに対応付けられているが,メモリ上の内容の方が新しく,ディスクへの書き込みが終わっていないメモリ領域のサイズ.この状態でメモリ内容を破棄すると情報をロストすることになるので怖い.故に Available 扱いでもない.遅延書き込みの書き込み待ちのデータもここに所属する.
ModifiedNoWrite
Modified 相当だが書き込みを意図的に行わないメモリ領域のサイズ.
Standby
Available 扱いのメモリ領域のうち,ディスク上のファイルまたはページングファイルに対応付けられていて,かつ内容がディスク上のものと同一なメモリ領域のサイズ.対応するファイルにアクセスがあったとき,このメモリ内容がそのまま使える.俗に言う「ディスクキャッシュ」の実体とも言える.ワーキングセットから外れてページファイルとの同期済みヒープも同様.Vista にて優先順位が導入され,数字が小さいほど優先度が低い.

「空きメモリの有効利用」という表現を,多くの人が誤解したまま使っています.「搭載物理メモリ 2 GB の環境で,プログラムが 1 GB 確保したから,空きメモリは 1 GB」なんてのは,間違いの最たる例です.Physical Memory の Available の定義をもう一度見直して下さい.それは単に OS が「その瞬間に物理メモリの内容を捨てても問題が起きない」とみなすかどうかの問題です.物理メモリが割り当てられていても,ページファイルに同期済みの領域はいつ捨てても問題ありません.つまりそこは「空きメモリ」です.



Windows のメモリ管理への理解を深めたい人は,ファイルコピーを行ったり,SetProcessWorkingSetSize API を呼び出したりしながらこれらの値がどう変化するか見てみるとよいでしょう.