システムにいくらメモリが搭載されていて、そのうちどのくらいのメモリが実際に使われているのか、本当に必要なメモリはどのくらいなのか。Windows OSのメモリ管理機能について解説。
前回はWindows OSのプロセスとスレッドについて解説した。今回はプロセスやスレッド管理とも深く関連する「メモリ管理」について見ていく。
Windows OSと、その上で動作しているプロセスがどのくらいのメモリを使用しているかを確認することは、PCにどのくらいのメモリを用意(搭載)すべきかを決めるために重要なことである。せっかく新しい高速なシステムを導入してもメモリが不足していたのではその性能を100%発揮できないからだ。
現在使用中のシステムにいくらメモリが搭載されていて、そのうちどのくらいのメモリが実際に使われているのか、本当に必要なメモリはどのくらいなのか、そもそも何に使われているのか、などを簡単に知るには、通常は「タスク マネージャー」を利用する。今回はこのタスクマネージャーのメモリ関連の表示などを使って、Windows OSにおけるメモリの使い方について見てみよう。
以下に、Windows 8.1におけるタスクマネージャーの画面例を示す。
タスクマネージャーの基本的な見方については関連記事を参照していただくとして、この「メモリ」グループの表示を見ると、現在のシステムにおけるメモリの利用状況が確認できる。上の例で言えば、システム全体の物理メモリサイズは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×プロセス数」とはならず、はるかに少なくなる。
最近では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では、プロセスを構成するコードやデータ、スタックなどのうち、実メモリ上に載っている部分を全部まとめて「ワーキングセット」と言い、そのサイズのことを「ワーキングセットサイズ」と呼んでいる。そして、プロセス全体を指して「コミットサイズ」と呼ぶ。正確には、プロセスの仮想アドレス空間のうち、ページを割り当てた部分のサイズをコミットサイズと呼ぶ。コミットされたページ(仮想アドレス空間上でコードやデータ、スタックなどを実際に割り当てたページアドレス領域)は、メモリ上にある場合もあるし、スワップアウトされて外部のページファイル上に存在する場合もある。
もう一度まとめると、プロセスに割り当てた仮想アドレス空間のサイズのことをコミットサイズ、そのうちオンメモリの部分をワーキングセットサイズという。
プロセスごとのワーキングセットサイズやコミットサイズなどは、タスクマネージャーの[詳細]タブで確認できる。
なお、各プロセスで同じDLLファイル(や共有メモリ)を参照している場合は、システム全体で1つのバイナリイメージが共有されるので(メモリ上の同じ場所を複数のプロセスから参照する)、より少ないメモリで済む。上の画面では、ワーキングセットサイズの内訳が、「メモリ(プライベート ワーキング セット)」と「メモリ(共有ワーキング セット)」の2つに分けて表示されている。一般的にはワーキングセットサイズの方がコミットサイズよりも小さいが、共有DLLを多く利用しているプロセスだとコミットサイズの方が小さくなることもある(共有DLLなどの分はコミットサイズには含まれないため)。
各プロセスでどのようなDLL(や共有メモリ)が使われているか、それぞれがどのアドレスに割り当てられているかなどは、SysinternalsのProcess Explorerのようなツールを利用すれば確認できる。
タスクマネージャーには「キャッシュ済み」という表示があるが、これはファイルのキャッシュとして利用されているメモリのサイズを表す。
Windows OSでは、プロセス用のメモリ領域と、ファイルシステム(のバッファーなど)が利用するメモリ領域を分けて管理しているわけではない。プロセス空間へのDLLファイルのマッピングと同様に、任意のファイルを(カーネル内部にある)ファイルキャッシュ用のメモリ領域にマッピングすることによってファイルアクセスを実現している。マップされたファイルからの読み出しや更新されたデータの遅延書き込みはカーネルメモリを管理するキャッシュマネージャーによって自動的に行われる。そしてシステム全体のメモリが不足すれば、古いキャッシュ領域のフラッシュ(アンマップ)などの処理が自動的に行われる。
どのくらいのメモリ領域がファイルのキャッシュとして使われているかは、タスクマネージャーの「キャッシュ済み」表示で、その概要を確認できる。より詳しく調べるにはタスクマネージャーの画面下部にある[リソース モニターを開く]をクリックする。するとリソースモニターが起動するので、[メモリ]タブを選択する。この画面の「物理メモリ」グループには、タスクマネージャーの「メモリ構成」グラフの詳細な内訳が表示されている。
画面中の数値を見ると分かるように、「キャッシュ済み」は「変更済み」と「スタンバイ」を加えたものである。ファイルからデータが読み出されてメモリ上にキャッシュされると「スタンバイ」となり、ファイルへデータを書き込むと「変更済み」になる(キャッシュを更新するだけで、ディスクへの書き出しは行わない)。変更済みのキャッシュデータは後で「lazy writer」機能によってディスクに順次書き出され、その後キャッシュは「スタンバイ」状態へ移行する。
lazy writerでは、基本的には1秒に1回のペースで変更済みキャッシュの内容をディスクに書き出す。そのため、しばらくすると次の画面のように、キャッシュ済みのサイズは変わらないまま、変更済みが減っていき、スタンバイが増えていく。
大量のファイルコピーなどを行うと、「空き」領域部分がなくなり、ほとんど全てが「使用中」と「変更済み」「スタンバイ」だけになる。しかし、特に問題はないだろう。先ほど述べたように、プロセスで必要なメモリサイズ(「使用中」領域)が増えてくると、キャッシュ済み領域が自動的に解放されるからだ。
タスクマネージャーのメモリ画面には「利用可能」という表示がある。これは上のリソースマネージャーの画面を見ても分かる通り、「スタンバイ」と「空き」の合計になっている。
「スタンバイ」はファイルをキャッシュしたものであり、その内容が失われても問題とはならない。少々遅くなるが、必要ならまたディスクから読み出してくればよいからだ。一方「空き」領域は、まだ何にも使われていないメモリ領域のことである。よってタスクマネージャーでは、この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.