
このシステム情報は Process Explorer から取得されます。使用可能な物理メモリはまだありますが、システムには RAM がほとんど残っていないことが示されています。
タスク マネージャーでは、合計 RAM の約 74% が使用されていることも表示されます。
Windows 8.1 をインストールしてから、コンピューターの RAM は 4+8=12 GB になりました。4 GB を 8 GB モジュールに変更してアップグレードしました。これが問題なのでしょうか? それとも、この動作は正常で、使用可能な物理メモリの意味を私が誤解しているだけなのでしょうか?
答え1
短い答え
「メモリ不足」ポップアップは、制限を超えていることを示していますプライベートコミットメモリ—仮想メモリの一種。RAM(物理メモリ)が不足しているわけではありません。利用可能利用可能なRAMが多ければ、コミット制限を超えることはできません。コミット制限は、 合計RAM (使用中かどうかに関係なく) と現在のページファイル サイズ。
逆に、コミット制限を「使い切る」もの (主にプロセス専用の仮想アドレス空間の作成) は、必ずしも RAM を使用するわけではありません。ただし、OS は、必要になった場合に格納する場所があることがわかっていない限り、その作成を許可しません。そのため、すべての RAM または RAM のほとんどを使用しなくても、コミット制限に達する可能性があります。
このため、ページファイルなしで実行しないでください。ページファイルは実際には書き込まれない可能性があることに注意してください。ただし、それでも「メモリ不足」や「メモリ不足」のエラーは回避できます。
中間回答
Windows には、実際には RAM が不足していることに関するエラー メッセージはありません。不足しているのは「コミット制限」です。
Process Explorer のそのバージョンの「システム」グラフの名前は適切ではありません。「コミット チャージ」というラベルを付けるべきです。(私が持っているバージョンでは「システム コミット」と呼ばれています。これは改善されましたが、まだ完全に一貫していません。) いずれにしても、グラフの「現在の」高さは、テキスト セクションの下部に「コミット チャージ」-「現在」として表示され、グラフの最大の高さは「コミット チャージ」-「制限」を表します。
「コミット チャージ」とは、ページファイル (ある場合) によってバックアップされる仮想アドレス空間を指します。言い換えると、RAM に収まらない場合は、残りがページファイルに格納されます。(他のファイルによってバックアップされる他の種類の VAS (「マップされた」VAS と呼ばれる) や、常に RAM 内に保持する必要がある VAS (後者は「非ページ可能」と呼ばれます) があります。) 「コミット リミット」とは、「コミット チャージ」の最大値です。これは、RAM サイズとページファイル サイズの合計に等しくなります。
どうやらページファイルがないようです (コミット制限が RAM サイズと等しいためわかります)。そのため、コミット制限は単純に RAM サイズになります。
どうやら、さまざまなプログラムと OS が、可能な最大コミットのほぼすべてを使用したようです。
これは、空きまたは使用可能な RAM の量とは直接関係ありません。はい、使用可能な RAM は約 4.5 GB あります。これは、コミット制限を超えてよいという意味ではありません。コミットされたメモリは必ずしも RAM を使用するわけではなく、使用可能な RAM の量によって制限されるわけではありません。
ページファイルを再度有効にする必要があります。これだけコミットされている場合、16 GB のページファイルをお勧めします。OS に RAM に大量のデータを保持するよう強制したくないからです。ページファイルは空き領域がたくさんある場合に最もよく機能します。または、RAM を追加します。かなり多く追加します。良好なパフォーマンスを得るには、ページファイルによってサポートされていない (ただし、他のファイルにページ アウトできる) コードやその他のデータ用に、RAM に十分な領域が必要です。
非常に長い回答
(しかし、メモリ管理の章よりはずっと短いですWindows 内部...)
プログラムがプロセス専用の仮想メモリを 100 MB 割り当てるとします。これは、VirtualAlloc 呼び出しで「コミット」オプションを使用して行われます。これにより、「コミット チャージ」が 100 MB 増加します。ただし、この「割り当て」では実際には RAM は使用されません。RAM は、新しくコミットされたメモリの一部が使用されるときにのみ使用されます。仮想アドレス空間初めてアクセスされます。
RAMが最終的にどのように使用されるか
(もしそうなるなら)
新しく割り当てられたスペースへの最初のアクセスは、ほとんどの場合メモリ書き込みになります(新しく割り当てられたプライベートVASを書き込む前に読み取ることは、ほとんどの場合プログラミングエラーです。厳密に言えば、その初期の内容は未定義だからです)。しかし、読み取りまたは書き込みのいずれの場合も、新しく割り当てられたVASのページに初めてアクセスすると、ページフォールト「フォールト」という言葉は聞こえが悪いですが、ページ フォールトは仮想メモリ OS では完全に予期される、さらには必要なイベントです。
この特定の種類のページ フォールトに応答して、ページャー (OS のメモリ マネージャーの一部で、"Mm" と略されることもあります) は次の処理を実行します。
- RAM の物理ページを割り当てます (理想的にはゼロ ページ リストから割り当てますが、いずれの場合も、Windows が「使用可能」と呼ぶもの、つまりゼロ、空き、またはスタンバイ ページ リストから優先順に割り当てます)。
- 記入してくださいページテーブルエントリ物理ページを仮想ページと関連付ける。そして最後に
- ページ フォールト例外を無視します。
After which the code that did the memory reference will re-execute the instruction that raised the page fault, and this time the reference will succeed.
We say that the page has been "faulted into" the process working set, and into RAM. In Task Manager this will appear as a one-page (4 KB) increase in the "private working set" of the process. And a one-page reduction in Available physical memory. (The latter may be tough to notice on a busy machine.)
Note 1: This page fault did not involve anything read from disk. A never-before-accessed page of committed virtual memory does not begin life on disk; it has no place on disk to read it from. It is simply "materialized" in a previously-Available page of RAM. Statistically, in fact, most page faults are resolved in RAM, either to shared pages that are already in RAM for other processes, or to the page caches - the standby or modified lists, or as "demand zero" pages like this one.
Note 2: This takes just one page, 4096 bytes, from "Available". Never-touched-before committed address space is normally realized—faulted in—just one page at a time, as each page is "touched" for the first time. There would be no improvement, no advantage, in doing more at a time; it would just take n times as long. By contrast, when pages have to be read from disk, some amount of "readahead" is attempted because the vast majority of the time in a disk read is in per-operation overhead, not the actual data transfer. The amount "committed" stays at 100 MB; the fact that one or pages have been faulted doesn't reduce the commit charge.
Note 3: Let's suppose that we have 4 GB "available" RAM. That means that we could reference already-allocated but never-before-referenced committed memory about a million more times (4 GB / 4096) before we'd be out of RAM. At which point, if we have a pagefile as David Cutler and Lou Perazzoli intended, some of the longest-ago-referenced pages in RAM would be saved on disk and then made Available for use in resolving these more recent page faults. (Actually the OS would initiate RAM reclamation methods like "working set trimming" rather before that, and the actual writes to the pagefile are cached and batched on the modified page list for efficiency, and and... ) None of that would affect the "committed" count. It is relevant, though, to the "commit limit". If there isn't room for all of "committed" memory in RAM, the excess can be kept in the pagefile. Thus the size of the pagefile contributes to the "commit limit".
And it keeps happening...
しかし、100 万回以上の参照は行わず、約 4 GB 相当のページが「使用可能」であると仮定します。次に、同じプロセス (または別のプロセス、どちらでもかまいません) が別の VirtualAlloc を実行し、今回は 200 MB をコミットするとします。この場合も、この 200 MB がコミット チャージに追加され、使用可能な RAM が削除されることはありません。アドレス空間を VirtualAlloc するだけでは、対応する量の RAM が使用されることはありません。また、「使用可能」な RAM が少ないと、VirtualAlloc できるアドレス空間の量が制限されることはありません (使用可能な RAM が多いと、アドレス空間の量が増えることもありません)。
(そうですね、オーバーヘッドはわずかですが、割り当てられた仮想アドレス空間の 2 MB (x86 の非 PAE システムの場合は 4 MB) ごとにページ テーブルに使用される 1 つの (ページング可能な!) ページがあり、仮想的に連続する割り当て範囲ごとに数十バイトの「仮想アドレス記述子」があります。)
この方法では、少量の RAM しか使用せずに大量の「コミット チャージ」を消費することが可能であり、これは一般的です。
では、仮想アドレス空間を「コミット」しても RAM が消費されないのであれば、なぜ制限が必要なのでしょうか?
「コミットチャージ」は潜在的な未来ストレージスペースの使用。「コミット制限」は、このような割り当てを保持するために使用できるストレージの合計量(RAM + ページファイルスペース)を表します。実際に参照され、どこかに保存する必要がある場合。
Mm が VirtualAlloc 要求を承認すると、割り当てられた領域への後続のすべてのメモリ アクセスが成功することを約束 (「約束」) します。ページ フォールトが発生する場合もありますが、RAM 内かページ ファイル内かに関係なく、すべてのページの内容を保持するのに十分なストレージがあるため、フォールトはすべて解決できます。Mm は、ストレージ スペースの容量 (コミット制限) と、すでに「コミット」されている容量 (現在のコミット チャージ) を認識しているため、これを認識します。
(ただし、それらのページすべてがまだアクセスされているとは限らないため、特定の時点でコミットされた量に対応する実際のストレージが必ずしも存在するわけではありません。)
それで...「システムのメモリが不足しています」はどうでしょうか?
VirtualAlloc を試行し、現在のコミット チャージと要求された割り当てサイズを足すとコミット制限を超え、OS がページファイルを拡張してコミット制限を増やすことができない場合は、「メモリ不足」ポップアップが表示され、プロセスは VirtualAlloc 呼び出しが失敗したと認識します。ほとんどのプログラムは、その時点で手を上げて終了します。一部のプログラムは、呼び出しが成功したと想定して盲目的に続行し、後で割り当てたと思われる領域を参照しようとして失敗します。
もう一度言いますが(繰り返して申し訳ありませんが)、使用可能なRAMの量は関係ありません。OSはRAMまたはページファイルスペースが意思必要なときに利用可能になるが、その約束は「利用可能」から減算されない。利用可能なRAMは、コミットされたVMによってのみ使用される。参照初めて、それが「フォールトイン」の原因になります...つまり、物理メモリで実現されます。そして、単に仮想メモリをコミットする (= 割り当てる) だけでは、それは起こりません。空いている仮想アドレス空間を取得し、そこから使用可能な仮想アドレス空間を作成するだけです。
しかし、「メモリ不足」の場合、コミットされたメモリの割り当て要求があり、OSは現在のコミットチャージをこの新しい要求のサイズに追加しました...そして合計は次のようになります。もっとコミット制限を超えています。OSがこの新しいものを承認した場合、そしてその後、そのすべてのスペースが参照されると、それをすべて保存する実際の場所 (RAM + ページファイル) はなくなります。
OS はこれを許可しません。最悪の場合、たとえすべてが「フォールトイン」されたとしても、保持できるスペースを超える量の VAS の割り当ては許可されません。これが「コミット制限」の目的です。
3度言います、3度言います、3度言います。「使用可能な」 RAM の量は重要ではありません。コミットされた仮想スペースがまだそのストレージ スペースをすべて実際に使用していないことは重要ではありません。将来的にすべてがフォールトインされる可能性がない限り、Windows は仮想割り当てに「コミット」できません。
「マップ」と呼ばれる別のタイプの VAS があり、これは主にコードや大きなデータ ファイルへのアクセスに使用されますが、「コミット料金」は請求されず、「コミット制限」によって制限されません。これは、独自のストレージ領域、つまり「マップ」されたファイルが付属しているためです。「マップ」された VAS の唯一の制限は、マップされたファイル用のディスク領域の量と、それらをマップするプロセス内の空き VAS の量です。
しかし、システムを見ると、まだコミット制限に達していないようです。
これは基本的に測定と記録保持の問題です。VirtualAlloc 呼び出しがすでに試行され、失敗した後のシステムを調べています。
コミット制限が 500 MB しか残っていないのに、あるプログラムが 600 MB の VirtualAlloc を試みたとします。その試みは失敗します。次にシステムを見て、「何? まだ 500 MB も残っているじゃないか!」と言います。実際には、その時点では問題のプロセスが完全になくなる可能性が高いため、その時点ではさらに多くのメモリが残っている可能性があります。つまり、そのプロセスに以前割り当てられたコミット メモリはすべて解放されているのです。
問題は、過去を振り返ってコミット料金がいくらだったか確認できないことだ。だった割り当てが試行された時点では、その試行がどのくらいのスペースを対象に行われたかはわかりません。そのため、試行が失敗した理由や、試行を成功させるには「コミット制限」をどれだけ大きくする必要があったかを明確に把握することはできません。
「システムは残り少なく「記憶に残る」って何ですか?
上記のケースで、OS がページファイルを拡張できる場合 (つまり、デフォルトの「システム管理」設定のままにするか、管理しているが最大値を初期値より大きく設定し、十分な空きディスク領域がある場合)、そのような拡張によってコミット制限が十分に増加し、VirtualAlloc 呼び出しが成功する場合、Mm はページファイルを拡張し、VirtualAlloc 呼び出しが成功します。
そして、そのときに「システムのメモリが不足しています」というメッセージが表示されます。これは、緩和策を講じずに状況が続くと、すぐに「メモリ不足」の警告が表示される可能性が高いという早期警告です。いくつかのアプリを閉じる必要があります。まずはブラウザ ウィンドウから始めましょう。
それが良いことだとお考えですか? ページファイルの拡張は悪です!!!
いいえ、そうではありません。OS は実際には既存のファイルを「拡張」しません。新しいエクステントを割り当てるだけです。効果は他の非連続ファイルとほとんど同じです。古いページファイルの内容はそのまま残ります。新しい場所にコピーしたりする必要はありません。ほとんどのページファイル IO はページファイル サイズに比べて比較的小さなチャンクであるため、転送がエクステント境界を越える可能性は非常にまれです。そのため、断片化は、非常に過度でない限り、それほど問題にはなりません。
最後に、拡張機能内のスペースを「コミット」したすべてのプロセスが終了すると (OS のシャットダウン時、またはそれより早く終了した場合)、エクステントは自動的に解放され、ページファイルは以前のサイズと割り当てに戻ります。以前連続していた場合は、再び連続した状態になります。
したがって、ページファイルの拡張を許可することは、完全に無料のセーフティネットとして機能します。許可してもシステムがそれを必要としない場合は、システムは「ページファイルを絶えず拡張および縮小する」ことはなく、コストがかかります。何もない必要になった場合、「仮想メモリ不足」エラーでアプリがクラッシュするのを防ぐことができます。
でも、でも、でも…
ページファイルの拡張を許可すると、Windows はページファイルを絶えず拡張および縮小し、デフラグを実行するまでページファイルが断片化されることになる、と多くの Web サイトで読みました。
彼らはただ間違っている。
「メモリが不足しています」(または、古いバージョンでは「仮想メモリが不足しています」) というポップアップが表示されない場合は、OS がページファイルを拡張したことがありません。
このポップアップが表示された場合、初期のページファイル サイズが小さすぎることを示しています。(私は、最大使用量の約 4 倍に設定することを好みます。つまり、「%pagefile usagepeak」パフォーマンス モニター カウンターは 25% 未満である必要があります。理由: ページファイル領域は他のヒープと同様に管理され、十分な空き領域がある場合に最もよく機能します。)
しかし、なぜ彼らはただ...
OSは割り当てをそのままにして、参照ページフォールトを解決するために利用できるRAMがない場合、失敗します。言い換えると、最初のページフォールトがどのように機能するかを説明した上で、「利用可能な物理ページのRAMを割り当てる」(手順1)が、利用可能なRAMがないため実行できなかった場合はどうなるでしょうか。そして何かをページングして利用できるようにするためのスペースは残っていなかったのですか?
そうすると、ページャーはページ フォールトを解決できなくなります。ページャーは、例外 (ページ フォールト) をフォールト スレッドに報告できるようにする必要があります (おそらく、他の例外コードに変更されます)。
設計哲学は、コミット制限を使い果たした場合、VirtualAlloc はアドレスではなくゼロ (技術的には NULL ポインタ) を返すというものです。また、VirtualAlloc 呼び出しが失敗する可能性があることをプログラマーが知っていると期待するのはまったく合理的です。したがって、プログラマーはそのようなケースをチェックし、それに応じて適切な対応を取ることが期待されます (その時点までの作業を保存する機会を与え、その後プログラムを「正常に」終了するなど)。(プログラマー: malloc、new などから NULL ポインターが返されるかどうかチェックしていますよね? では、なぜこれをチェックしないのですか?)
しかし、プログラマーは次のような単純なメモリ参照が
i = 0; // initialize loop counter
失敗する可能性があります - 正常にコミットされたアドレス空間の領域内にある場合はそうではありません。 (または、マップされたアドレス空間の場合も同様です。) しかし、これは、「オーバーコミットされた割り当てを許可し、メモリ参照を失敗させる」という哲学に従った場合に発生する可能性があります。
残念ながら、上記のコード行のようなメモリ参照には、不良ステータスを返す便利な方法がありません。仕事加算や減算と同じように、このような失敗を報告する唯一の方法は例外として報告することです。したがって、これらを処理するには、プログラマーはプログラム全体を例外ハンドラーでラップする必要があります。(try ... catch など)
それは可能です...しかし、コード内で例外が発生する可能性のあるポイントが非常に多いため、ハンドラがそれらの例外に対して「適切な処理」を行う方法を知ることは困難です。(具体的には、毎VirtualAlloc されたメモリ、malloc または new で割り当てられたメモリへのメモリ参照...、およびスタックも VirtualAlloc されるため、すべてのローカル変数へのメモリ参照。
つまり、このような場合にプログラムを適切に失敗させることは非常に困難です。
一方、VirtualAlloc (または malloc や new など、まったく同じではありませんが) から NULL ポインターが返されたかどうかをチェックし、その後、プログラムがその仮想空間を必要としていたことを実行しようとしないなど、適切な処理を実行するのは非常に簡単です。また、これまでの作業を保存するかどうかをユーザーに尋ねることもできます (ただし、多くのアプリはそこまでの作業すら行いません)。
コミットの他のユーザー
Incidentally, the "commit limit" is not reduced by the OS's various allocations such as paged and nonpaged pool, the PFN list, etc.; these are just charged to commit charge as they happen. Nor is commit charge or commit limit affected by video RAM, or even video RAM "window" size, either.
Test it yourself
You can demo all of this with the testlimit tool from the SysInternals site. Option -m will allocate committed address space but will not "touch" it, so will not cause allocation of RAM. Whereas option -d will allocate and also reference the pages, causing both commit charge to increase and available RAM to decrease.
References
Windows Internals by Russinovich, Solomon, and Ionescu. There are even demonstrations allowing you to prove all of these points using the testlimit tool. However, I must warn you that if you think this was long, be warned: the Mm chapter alone is 200 pages; the above is an EXTREMELY simplified version. (Please also glance at the "Acknowledgements" section in the Introduction.)
See also MSDN VirtualAlloc documentation
答え2
Maybe to add up to the brilliant accepted answer:
Windows and most programms assume, that they can commit as much (virtual) memory as needed. This is one of the big reasons why one should not disable the pagefile, see proposed fact 2.2 in my superuser question.
I also link to this brilliant serverfault answer there, which makes clear, how the pagefile works:
Many people seem to assume that Windows pushes data into the pagefile on demand. EG: something wants a lot of memory, and there is not enough RAM to fill the need, so Windows begins madly writing data from RAM to disk at this last minute, so that it can free up RAM for the new demands.
This is incorrect. There's more going on under the hood. Generally speaking, Windows maintains a backing store, meaning that it wants to see everything that's in memory also on the disk somewhere. Now, when something comes along and demands a lot of memory, Windows can clear RAM very quickly, because that data is already on disk, ready to be paged back into RAM if it is called for. So it can be said that much of what's in pagefile is also in RAM; the data was preemptively placed in pagefile to speed up new memory allocation demands.
Further reading is provided here