第4回 メモリ管理:Windows OS入門
システムにいくらメモリが搭載されていて、そのうちどのくらいのメモリが実際に使われているのか、本当に必要なメモリはどのくらいなのか。Windows OSのメモリ管理機能について解説。
前回はWindows OSのプロセスとスレッドについて解説した。今回はプロセスやスレッド管理とも深く関連する「メモリ管理」について見ていく。
タスクマネージャーでメモリの利用状況を確認する
Windows OSと、その上で動作しているプロセスがどのくらいのメモリを使用しているかを確認することは、PCにどのくらいのメモリを用意(搭載)すべきかを決めるために重要なことである。せっかく新しい高速なシステムを導入してもメモリが不足していたのではその性能を100%発揮できないからだ。
現在使用中のシステムにいくらメモリが搭載されていて、そのうちどのくらいのメモリが実際に使われているのか、本当に必要なメモリはどのくらいなのか、そもそも何に使われているのか、などを簡単に知るには、通常は「タスク マネージャー」を利用する。今回はこのタスクマネージャーのメモリ関連の表示などを使って、Windows OSにおけるメモリの使い方について見てみよう。
以下に、Windows 8.1におけるタスクマネージャーの画面例を示す。
タスクマネージャーによるメモリ使用量の確認
これは64bit版Windows 8.1のタスクマネージャーの「パフォーマンス」タブでメモリの使用量を確認しているところ。Windows 7以前のタスクマネージャーとは表示形式が異なるが、表示されている内容やその意味はほぼ同じである。
(1)このタブを選択する。
(2)メモリを選択する。
(3)実装されている実際の物理メモリサイズと、Windows OSから利用できる最大物理メモリサイズ。内蔵グラフィックスなどのために1Gbytes分少なくなっている。
(4)物理メモリの使用量のグラフ。
(5)メモリの利用内訳。リソースモニターのメモリ画面を簡易表示したもの。
(6)使用中の物理メモリサイズと、残りの物理メモリサイズ。
(7)現在のコミットサイズと、最大可能コミットサイズ(システムメモリサイズ+ページファイルサイズ)。
(8)ファイルキャッシュとして利用されているメモリサイズ。
(9)カーネルのページプールと非ページプールサイズ。
(10)物理メモリの属性と予約済みサイズ。
タスクマネージャーの基本的な見方については関連記事を参照していただくとして、この「メモリ」グループの表示を見ると、現在のシステムにおけるメモリの利用状況が確認できる。上の例で言えば、システム全体の物理メモリサイズは16Gbytesで、現在はそのうち3.8Gbytesだけ使用している(「使用中」の値)、ということが分かる。
ではこのシステムの場合、メモリが4Gbytesもあれば十分で、残りの12Gbytesは無駄なのかというと、実はそうでもない。上の画面をよく見ると、他にも「コミット済み」が4.6Gbytes、「キャッシュ済み」が6.4Gbytes、といった数値が表示されている。システムに搭載されているメモリが十分かどうか判断するには、これらの値の意味を理解する必要がある。
プロセスごとのメモリアドレス空間
最初に、プロセスのアドレス空間について解説する。
システム内部では複数のプロセスやスレッドが動作しているということは前回述べた。ユーザーが起動したアプリケーションプログラムだけでなく、ユーザーセッションを構成するプロセスやシェル(Explorerなど)、サービス、サブシステム、OSカーネルなど、さまざまなものがプロセスとして実装され、相互に通信しながら動作している。
各プロセスは、2Gbytesもしくは8Tbytesのアドレス空間を持ち(次の表参照)、その中にプロセスを構成するプログラムコードやデータ、スタックなどが配置される。
アドレス空間 | 32bit Windows | 64bit Windows |
---|---|---|
ユーザープロセス空間 | 2Gbytes | 8Tbytes |
カーネルプロセス空間 | 2Gbytes | 16Ebytes |
Windows OSで利用可能なプロセスごとの最大アドレス空間サイズ 「ユーザー空間」は、1つのユーザープロセスごとに利用可能なメモリアドレス空間。例えば32bitのWindows OSでは、プロセスごとに最大2Gbytesのアドレス空間が利用できる。なお32bit Windows OSでは、ユーザー空間を3Gbytesに広げるオプション構成も利用できる。 |
ただしこのアドレス空間のうち、プロセスには実際に利用している部分にのみ実メモリを割り当てるので、システム全体で必要なメモリは「2Gbytes×プロセス数」とはならず、はるかに少なくなる。
32bit Windowsと64bit Windows
最近では64bit版のWindowsを搭載したPCが一般的になってきた。32bit Windowsと比較すると、64bit Windowsでは1プロセスで利用できるアドレス空間が広くなっており、2Gbytesを超えるような大きなプログラムやデータを利用できるようになっている。もっとも1つのプログラムでこのような大きなプログラムコードやデータが使われることはほとんどないので、これはあまりメリットではない。
64bit Windows OSの最も有利な点は、利用可能な最大物理メモリサイズが4Gbytes以上になっているという点にある。一般的な32bitシステムでは最大でも3Gbytes程度までしかメモリを利用できないが、64bit Windowsでは最大512Gbytes(Windows 8.1 Proの場合)も利用できる。昨今では、WebブラウザーやOfficeアプリケーションなどを同時に起動して多くのウィンドウを開いたりすれば、使用中のメモリサイズが3Gbytesを超すことも珍しくない。そのような環境では、64bitアプリケーションを持っていなくても、64bit Windowsへ移行する価値が高い。
プロセスのワーキングセットサイズとコミットサイズ
プロセスが動作するためには、プロセスを構成するプログラムコードやデータ、ヒープ、スタックなどがあらかじめメモリ上に適切にロードされていなければならない。もしメモリが不足していて、プログラムコードやデータの一部がメモリ上になければ、CPUはそこで実行をいったん停止/中断(ページフォルト)するしかない。そして例えばディスクから不足しているコードやデータなどをメモリ上へロード(ページインもしくはスワップイン)してから実行を再開する(逆に、メモリ不足時にページを書き出すことをページアウトやスワップアウトという)。全体としては非常に遅くなるが、まったく動作しなくなるわけではないし、ほとんどの場合ユーザーは止まっていることに気が付かないだろう。
これがWindowsでも利用している仮想記憶システムの原理である。このシステムでCPUが最大限性能を発揮するには、なるべくスワップイン/スワップアウトを起こさないように、可能な限り多くのメモリを割り当てておく必要がある。プロセス全体を全てメモリ上にロードできればよいが、そうでない場合はプロセス全体の中から、「最もよく使われそうな部分」を何らかの方法で選んでメモリ上へロードしておく。そうでない部分、つまり呼び出される頻度の低い部分はページフォルトが起こってからロードして実行してもよいだろう。実際これでも十分実用的に動作する。
ところでこの「最もよく使われそうな部分」は、OS用語で「ワーキングセット」という。ワーキングセット全体が常にメモリ上に存在するように管理しないと(ページフォルトなどで)実行パフォーマンスが大幅に低下する。
Windows OSでは、プロセスを構成するコードやデータ、スタックなどのうち、実メモリ上に載っている部分を全部まとめて「ワーキングセット」と言い、そのサイズのことを「ワーキングセットサイズ」と呼んでいる。そして、プロセス全体を指して「コミットサイズ」と呼ぶ。正確には、プロセスの仮想アドレス空間のうち、ページを割り当てた部分のサイズをコミットサイズと呼ぶ。コミットされたページ(仮想アドレス空間上でコードやデータ、スタックなどを実際に割り当てたページアドレス領域)は、メモリ上にある場合もあるし、スワップアウトされて外部のページファイル上に存在する場合もある。
もう一度まとめると、プロセスに割り当てた仮想アドレス空間のサイズのことをコミットサイズ、そのうちオンメモリの部分をワーキングセットサイズという。
プロセスごとのワーキングセットサイズやコミットサイズなどは、タスクマネージャーの[詳細]タブで確認できる。
プロセスの詳細表示
これはWindows 8.1のタスクマネージャーで[詳細]表示タブを選択したところ。各プロセスごとの詳細な情報を取得できる。ただし「ワーキングセット」などの情報を表示させるには、一番上の列名を右クリックして[列の選択]を実行すること。Windows 7やそれ以前のタスクマネージャーの場合は、[プロセス]タブを選んで[表示]−[列の選択]を実行する
(1)このタブを選択する。
(2)プロセスのワーキングセットサイズ。次の(3)と(4)を加えたもの。
(3)プロセスのワーキングセットのうち、非共有部分のサイズ。
(4)プロセスのワーキングセットのうち、共有部分のサイズ。
(5)コミットサイズ、つまりこのプロセスがコミットした(確保した)仮想アドレス空間のサイズ。その実体は実メモリ上にあることもあるし、ディスク上にスワップアウトされていることもある。
なお、各プロセスで同じDLLファイル(や共有メモリ)を参照している場合は、システム全体で1つのバイナリイメージが共有されるので(メモリ上の同じ場所を複数のプロセスから参照する)、より少ないメモリで済む。上の画面では、ワーキングセットサイズの内訳が、「メモリ(プライベート ワーキング セット)」と「メモリ(共有ワーキング セット)」の2つに分けて表示されている。一般的にはワーキングセットサイズの方がコミットサイズよりも小さいが、共有DLLを多く利用しているプロセスだとコミットサイズの方が小さくなることもある(共有DLLなどの分はコミットサイズには含まれないため)。
各プロセスでどのようなDLL(や共有メモリ)が使われているか、それぞれがどのアドレスに割り当てられているかなどは、SysinternalsのProcess Explorerのようなツールを利用すれば確認できる。
共有されるDLL
これはSysinternalsに含まれるProcess Explorerというツールで、あるプロセスの詳細を表示させたところ。DLLがロードされている論理アドレスとDLLのファイル名が表示されている。ほとんどのアプリケーションプログラムは何らかのDLLを参照しているが、同じDLLはメモリ上には1つだけしかロードされず、そのDLLを利用する全プロセスで共有している。
(1)プロセスを1つ選択する。
(2)これがプロセスのサイズ。
(3)プロセスアドレス空間内で、DLL(ファイル)がロードされている論理アドレス(正確にはメモリマッピングされている論理アドレス)。
(4)DLLファイル名。
ディスクキャッシュサイズ
タスクマネージャーには「キャッシュ済み」という表示があるが、これはファイルのキャッシュとして利用されているメモリのサイズを表す。
Windows OSでは、プロセス用のメモリ領域と、ファイルシステム(のバッファーなど)が利用するメモリ領域を分けて管理しているわけではない。プロセス空間へのDLLファイルのマッピングと同様に、任意のファイルを(カーネル内部にある)ファイルキャッシュ用のメモリ領域にマッピングすることによってファイルアクセスを実現している。マップされたファイルからの読み出しや更新されたデータの遅延書き込みはカーネルメモリを管理するキャッシュマネージャーによって自動的に行われる。そしてシステム全体のメモリが不足すれば、古いキャッシュ領域のフラッシュ(アンマップ)などの処理が自動的に行われる。
Rammapツールによるメモリの利用状況の確認
SysinternalsのRammapツールを使うと、メモリ(ページ)の利用状況やファイルマップ、プロセスメモリなどの詳細な状態を調査できる。これは物理メモリ順に、メモリページ(1ページ=4Kbytes)の利用状況を表示させたところ。プロセス用のメモリ(ページ)も、ファイルマッピング用のページも、全てキャッシュマネージャーによって統一的に管理されている。
(1)物理ページごとの用途を見るにはこのタブを選択する。
(2)メモリページの物理アドレス。x86/x64アーキテクチャのCPUとWindows OSの組み合わせでは、1ページは4Kbytesになる。
(3)メモリページの用途。1ページごとにファイルマッピングや共有メモリ、プロセスプライベートなど、さまざまな用途に使われている。Windows OSではこのように、1つのキャッシュマネージャーでプロセス用メモリもファイルマッピング(ファイルキャッシュ)用メモリもまとめて管理している。
(4)このページにマップされているファイルの名前。
どのくらいのメモリ領域がファイルのキャッシュとして使われているかは、タスクマネージャーの「キャッシュ済み」表示で、その概要を確認できる。より詳しく調べるにはタスクマネージャーの画面下部にある[リソース モニターを開く]をクリックする。するとリソースモニターが起動するので、[メモリ]タブを選択する。この画面の「物理メモリ」グループには、タスクマネージャーの「メモリ構成」グラフの詳細な内訳が表示されている。
リソースモニターによる詳細表示
リソースモニターでは、各リソースについて、より詳細な内容が表示される。
(1)このタブを選択する。
(2)ハードウェアなどによって予約されているメモリ。Windows OSの管轄外。このシステムの場合は、CPU内蔵のグラフィックス用VRAMが確保されている。
(3)プロセスやカーネルなどで使用中のメモリ領域。
(4)ファイルキャッシュとして使用中の領域のうち、未書き込みデータが残っている領域(ダーティバッファー領域)。この内容は随時ディスクへ遅延書き込まれ、その後はスタンバイ領域になる。
(5)ファイルキャッシュとして使用中の領域のうち、ディスク上に同じデータがある領域。もしシステム全体のメモリが不足したなら、この領域を空きメモリとして利用できる。
(6)システム起動時からまだ使っていないか、使用が済んで解放されたメモリ。
(7)変更済みとスタンバイを加えたものがキャッシュ済みになる。
画面中の数値を見ると分かるように、「キャッシュ済み」は「変更済み」と「スタンバイ」を加えたものである。ファイルからデータが読み出されてメモリ上にキャッシュされると「スタンバイ」となり、ファイルへデータを書き込むと「変更済み」になる(キャッシュを更新するだけで、ディスクへの書き出しは行わない)。変更済みのキャッシュデータは後で「lazy writer」機能によってディスクに順次書き出され、その後キャッシュは「スタンバイ」状態へ移行する。
lazy writerでは、基本的には1秒に1回のペースで変更済みキャッシュの内容をディスクに書き出す。そのため、しばらくすると次の画面のように、キャッシュ済みのサイズは変わらないまま、変更済みが減っていき、スタンバイが増えていく。
ディスクフラッシュ後の画面
上の画面からしばらく経過した後の状態。変更済み領域はlazy writer(遅延書き込み機能)によって順次ディスクに書き出され、サイズが縮小した。だがその分はスタンバイ領域になったので、キャッシュ済みサイズは変わらない。
(1)ダーティーバッファー領域の内容はほとんど全てディスクへ書き出された。
(2)ディスクへの書き出し後はスタンバイ領域になったので、この部分のサイズが増えた。
(3)変更済みとスタンバイの合計は変わらない。
大量のファイルコピーなどを行うと、「空き」領域部分がなくなり、ほとんど全てが「使用中」と「変更済み」「スタンバイ」だけになる。しかし、特に問題はないだろう。先ほど述べたように、プロセスで必要なメモリサイズ(「使用中」領域)が増えてくると、キャッシュ済み領域が自動的に解放されるからだ。
「利用可能」「空き」領域について
タスクマネージャーのメモリ画面には「利用可能」という表示がある。これは上のリソースマネージャーの画面を見ても分かる通り、「スタンバイ」と「空き」の合計になっている。
「スタンバイ」はファイルをキャッシュしたものであり、その内容が失われても問題とはならない。少々遅くなるが、必要ならまたディスクから読み出してくればよいからだ。一方「空き」領域は、まだ何にも使われていないメモリ領域のことである。よってタスクマネージャーでは、この2つの領域を合わせて「利用可能」と表示している。
「ページプール」と「非ページプール」とは
タスクマネージャーには「ページプール」と「非ページプール」という項目がある。これらは主にカーネル内部で利用されているメモリの用途を表したものだ。「ページプール」はページング可能(メモリ不足時にスワップアウトしてもよいページ)、「非ページプール」はページング不可能(スワップアウト不可の用途で使われるページ)という意味である。
ただ、これらは一般ユーザーには関係がないので気にしなくてもよい。この2つのメモリサイズ表示の内容は、すでに「使用中」の数値中に含まれているので、この分のメモリを新たに用意するなどの必要性はない。
「ハードウェア予約済み」とは
リソースマネージャーのメモリ表示画面には「ハードウェア予約済み」という項目がある(上の画面では「1121MB」となっている)。これは、システムに装着されている物理メモリのうち、ビデオカードのようなハードウェアやWindows OS以外の何らかの機能がこの部分を使っていて、Windows OSからも、そして当然ユーザーからも直接利用することができなくなっている、という意味である。
上の画面例でいうと、このシステムのCPU内蔵グラフィックス機能が1GbytesほどのメモリをグラフィックVRAM用として確保している。そのためWindows OSから見えるメモリサイズは、実際の物理的なメモリ容量である16Gbytesではなく、1Gbytes分少ない14.9Gbytesになっている。
今回はWindows OSのメモリ管理について見てきた。これだけ理解していれば、システムにどのくらいの物理メモリが必要か判断できるだろう(TIPS「タスク・マネージャのパフォーマンスタブの見方」参照)。次回はファイルシステムについて解説する予定である。
Copyright© Digital Advantage Corp. All Rights Reserved.