短い答え
「メモリ不足」ポップアップは、プライベートコミットメモリ(仮想メモリの一種)の制限を使い果たしたことを示します。RAM(物理メモリ)が不足しているわけではありません。使用可能な RAMの量は問題ではありません。使用可能なRAMをたくさん用意しても、コミットの制限を超えることはできません。コミット制限は、 RAMの合計(使用中かどうかにかかわらず)と現在のページファイルサイズの合計です。
逆に、コミット制限を「使い果たす」もの(ほとんどがプロセスプライベート仮想アドレススペースの作成)は、必ずしもRAMを使用しません。しかし、OSは、必要に応じて保存する場所があることがわかっていない限り、作成を許可しません。そのため、RAMのすべて、またはRAMのほとんどを使用しなくても、コミット制限に達する可能性があります。
これが、ページファイルなしで実行すべきではない理由です。ページファイルは実際には書き込まれないかもしれないことに注意してください!ただし、「メモリ不足」および「メモリ不足」エラーを回避できます。
中間回答
Windowsには、実際にはRAMが不足していることを示すエラーメッセージはありません。不足しているのは「コミット制限」です。
そのバージョンのプロセスエクスプローラーの「システム」グラフの名前はあまりありません。「commit charge」とラベル付けする必要があります。(バージョンでは、「システムコミット」と呼ばれています。より良いですが、完全に一貫性はありません。)いずれにしても、グラフの「現在の」高さは、「コミットチャージ」-現在」、グラフの最大高さは「Commit Charge」-「Limit」を表します。
「コミットチャージ」とは、ページファイル(存在する場合)によってバッキングされる仮想アドレス空間を指します。つまり、RAMにすべて収まらない場合、残りはページファイルに格納されます。(他のファイルによってバッキングされるタイプの他のタイプがあります-「マップされた」バスと呼ばれます-または常にRAMにとどまる必要があります;後者は「ページング不可」と呼ばれます。)「コミット制限」は、 「コミットチャージ」が可能です。RAMサイズにページファイルサイズを加えたものに等しくなります。
ページファイルがないようです(コミット制限がRAMサイズに等しいためわかります)。したがって、コミット制限は単にRAMサイズです。
さまざまなプログラムとOSが、可能な限り最大のコミットをほぼすべて使用しているようです。
これは、RAMの空き容量または利用可能容量とは直接関係ありません。はい、約4.5 GBのRAMが使用可能です。これは、コミットの制限を超えることができるという意味ではありません。コミットされたメモリは必ずしもRAMを使用するわけではなく、使用可能なRAMの量によって制限されません。
ページファイルを再度有効にする必要があります-これほどコミットされたものを使用して、16GBのページファイルをお勧めします多くの空きスペースがあります-または、RAMを追加します。もっとたくさん。良好なパフォーマンスを得るには、ページファイルに裏付けされていないコード(および他のファイルにページアウトできる)のためのRAMに十分なスペースが必要です。
非常に長い回答
(ただし、Windows Internalsのメモリ管理の章よりもはるかに短い...)
プログラムが100 MBのプロセスプライベート仮想メモリを割り当てるとします。これは、「commit」オプションを指定したVirtualAlloc呼び出しで行われます。これにより、「コミット料」が100 MB増加します。しかし、この「割り当て」は実際にはRAMを使用しません!RAMは、新しくコミットされた仮想アドレス空間の一部が初めてアクセスされるときにのみ使用されます。
RAMが最終的に使用される方法
(もしそうなら)
新しくコミットされたスペースへの最初のアクセスは、ほとんどの場合メモリ書き込みです(厳密に言えば、初期コンテンツは厳密には定義されていないため、書き込み前に新しく割り当てられたプライベートvasを読み取ることはほとんど常にプログラミングエラーです)。しかし、新しく割り当てられたvasのページに初めて触れると、読み取りまたは書き込みの結果がページフォールトになります。「フォールト」という言葉は良くないように聞こえますが、ページフォールトは仮想メモリOSで完全に予想されるイベントであり、必要なイベントですらあります。
この特定のタイプのページフォールトに応答して、ページャー(OSのメモリマネージャーの一部で、これを「Mm」と略すことがあります)は次のようになります。
- RAMの物理ページを割り当てます(理想的にはゼロページリストからですが、いずれにせよ、それはWindowsが「利用可能」と呼ぶものから来ます:ゼロ、フリー、またはスタンバイページリスト、優先順)。
- 物理ページを仮想ページに関連付けるためにページテーブルエントリに入力します。そして最後に
- ページフォールト例外を閉じます。
その後、メモリ参照を実行したコードは、ページフォールトを発生させた命令を再実行し、今回は参照が成功します。
ページがプロセスワーキングセットおよびRAMに「フォールト」されたと言います。タスクマネージャーでは、これはプロセスの「プライベートワーキングセット」の1ページ(4 KB)の増加として表示されます。また、使用可能な物理メモリが1ページ削減されます。(後者は、忙しいマシンでは気づきにくいかもしれません。)
注1:このページフォールトには、ディスクから読み取られたものは含まれていません。コミットされた仮想メモリのこれまでにアクセスされたことのないページは、ディスク上で起動しません。それを読むためにディスク上にない場所がありませんからを。これは、RAMの以前に使用可能なページで単に「具体化」されます。統計的には、実際、ほとんどのページフォールトはRAMで、他のプロセス用に既にRAMにある共有ページ、またはページキャッシュ(スタンバイリストまたは変更リスト)、またはこのような「デマンドゼロ」ページに解決されます。
注2:これは、「Available」から1ページ、4096バイトのみを取得します。各ページが初めて「タッチ」されるため、通常、タッチされる前にコミットされたアドレススペースは、一度に1ページだけで実現されます(フォールトインされます)。一度に多くのことを行っても、改善も利点もありません。ちょうどn倍の時間がかかります。対照的に、ページをディスクから読み取る必要がある場合、ディスク読み取りのほとんどの時間は実際のデータ転送ではなく、操作ごとのオーバーヘッドであるため、ある程度の「先読み」が試行されます。「コミット済み」の量は100 MBのままです。1つまたは複数のページに障害が発生しているという事実は、コミット料を削減するものではありません。
注3:4 GBの「使用可能な」RAMがあるとします。つまり、RAMが不足する前に、既に割り当てられているがまだ参照されていないコミット済みメモリを約100万回(4 GB / 4096)参照することができます。その時点で、David CutlerとLou Perazzoliが意図したページファイルがある場合、RAMで最も長く参照されたページの一部がディスクに保存され、これらの最近のページフォールトの解決に使用できるようになります。(実際には、OSはその前に「ワーキングセットトリミング」などのRAMレクラメーションメソッドを開始し、ページファイルへの実際の書き込みは、効率のために変更されたページリストにキャッシュされ、バッチ処理されます。 「コミット済み」カウント。ただし、これは「コミット制限」に関連しています。すべてのスペースがない場合
そして、それは起こり続けます...
しかし、これらの数百万件の参照をまだ行っておらず、約4GBの「利用可能な」ページがまだ残っているとしましょう。ここで、同じプロセス(または別のプロセス)が別のVirtualAllocを実行し、今度は200 MBがコミットされたとします。繰り返しになりますが、この200 MBはコミット料金に追加され、使用可能なRAMは削除されません。単にVirtualAlloc'atingアドレス空間は対応する量のRAMを使い果たしません。また、「使用可能な」RAMが少なくても、VirtualAllocが使用できるアドレス空間の量を制限しません(使用可能なRAMを増やしても増加しません)。
(まあ、OK ...少しのオーバーヘッドがあり、2 MB(x86、非PAEシステムの場合は4 MB)ごとにページテーブルに使用される1ページ(ページング可能!)仮想アドレス空間が割り当てられ、実質的に連続した割り当て範囲ごとに数十バイトの「仮想アドレス記述子」があります。
このようにして可能です-そして一般的です!-少量のRAMのみを使用しながら、大量の「コミットチャージ」を使用する。
それで、「コミット」仮想アドレス空間がRAMを使い果たしていない場合、なぜ制限が必要なのでしょうか?
「コミット料」は、ストレージスペースの潜在的な将来の使用を表すためです。「コミット制限」は、そのような割り当てを実際に参照し、どこかに格納する必要がある場合に、そのような割り当てを保持するために使用可能なストレージ(RAM +ページファイル領域)の合計量を表します。
MmがVirtualAlloc要求を承認するとき、割り当てられた領域への後続のすべてのメモリアクセスが成功することを約束します。ページフォールトが発生する可能性がありますが、RAMでもページファイルでも、これらすべてのページのコンテンツを保持するのに十分なストレージがあるため、フォールトはすべて解決できます。Mmは、ストレージスペースの量(コミット制限)とすでに「コミット」されている量(現在のコミット料金)を知っているため、これを知っています。
(ただし、これらのページはすべてまだアクセスされているとは限らないため、特定の時点でコミットされた量に対応する実際のストレージがあるとは限りません。)
それで...「システムのメモリ不足」はどうですか?
VirtualAllocを試行し、現在のコミット料金と要求された割り当てサイズがコミット制限を超える場合、OSはコミット制限を増やすためにページファイルを拡張できません...「メモリ不足」ポップを取得します-そして、プロセスはVirtualAlloc呼び出しが失敗したことを確認します。ほとんどのプログラムは、その時点で手を放して死にます。呼び出しが成功したと仮定して、盲目的に押す人もいれば、後で割り当てたと考えた領域を参照しようとすると失敗する人もいます。
繰り返しますが(繰り返しはごめんなさい):使用可能なRAMの量は問題ではありません。OSは、必要なときにRAMまたはページファイルのスペースを利用できると約束しましたが、その約束は「使用可能」から差し引かれません。使用可能なRAMは、初めて参照されたときにコミットされたvmによってのみ使用されます。これにより、「faulted in」が発生します。つまり、物理メモリで実現されます。そして、単純に仮想メモリをコミット(=割り当て)しても、それは行われません。無料の仮想アドレス空間のみを取得し、使用可能な仮想アドレス空間を作成します。
しかし、「アウトメモリの」場合にコミットされたメモリの割り当て要求があっただし、OSは現在、このneew要求のサイズに電荷をコミット追加...と合計であることを発見したより多くの制限をコミットするよりも。OSは、この新しいものを承認し、もしそうならばとスペースがその後参照されたすべてのことを、それをすべてを格納するための任意の実際の場所(RAM +ページファイル)は存在しないでしょう。
OSはこれを許可しません。最悪の場合にそれを保持するスペースがあるよりも多くのvasを割り当てることはできません-たとえすべてが「障害」になったとしてもです。それが「コミット制限」の目的です。
3回教えます3回教えます3回教えます:「使用可能な」RAMの量は重要ではありません。コミットされた仮想スペースが実際にすべてのストレージスペースをまだ使用していないことは問題ではありません。Windowsは、将来すべてがフォールトされる可能性がない限り、仮想割り当てを「コミット」できません。
主にコードと大きなデータファイルへのアクセスに使用される「マップ」と呼ばれる別のタイプのvasがありますが、「commit charge」には課金されず、「commit limit」によって制限されないことに注意してください。これは、独自のストレージ領域、つまり「マッピングされた」ファイルが付属しているためです。「マップされた」vasの唯一の制限は、マップされたファイル用のディスクスペースの量と、それらをマップするプロセス内の空きvasの量です。
しかし、システムを見ると、まだコミットの限界に達していないのですか?
それは基本的に測定と記録の保持の問題です。VirtualAlloc呼び出しが既に試行されて失敗した後、システムを見ています。
コミット制限が500 MBしか残っておらず、一部のプログラムが600 MBのVirtualAllocを試行したとします。試行は失敗します。次に、システムを見て、「何?まだ500 MBが残っています!」と言います。実際、その時点までに問題のプロセスが完全に消失している可能性が高いため、それまでに多くのことが残っている可能性があります。
問題は、時間をさかのぼって、allocの試行が行われた時点でコミットチャージが何であったかを確認できないことです。そして、あなたはその試みがどれだけのスペースのためだったかも知らない。そのため、試行が失敗した理由や、それを機能させるためにさらに「コミット制限」が必要になったことが明確にわかりません。
私は、「システムがされて見てきた低ランニングメモリ上に」。あれは何でしょう?
上記の場合、OSがページファイルを展開できる場合(つまり、デフォルトの「システム管理」設定のままにするか、管理するが最大値を初期値より大きく設定し、かつ十分な空きディスク容量がある場合)、およびこのような展開により、コミット制限が十分に大きくなり、VirtualAlloc呼び出しが成功します。その後、Mmがページファイルを展開し、VirtualAlloc呼び出しが成功します。
そして、それは「システムのメモリが不足しています」と表示されたときです。これは、問題が緩和されずに継続すると、「メモリ不足」の警告がすぐに表示される可能性があるという早期警告です。一部のアプリを閉じる時間です。私はあなたのブラウザウィンドウから始めます。
そして、あなたはそれが良いことだと思いますか?ページファイルの展開は悪です!!!
いいえ、そうではありません。OSが実際に既存のファイルを「拡張」するわけではありません。新しいエクステントを割り当てるだけです。この効果は、他の不連続ファイルとほとんど同じです。古いページファイルの内容はそのままです。新しい場所などにコピーする必要はありません。ほとんどのページファイルIOはページファイルサイズと比較して比較的小さなチャンクであるため、特定の転送がエクステント境界を越える可能性は非常にまれであるため、断片化は実際に過度でない限りそれほど害はありません。
最後に、拡張機能の「コミット」スペースを持つすべてのプロセスが終了すると(OSのシャットダウンではなく、すぐに)、エクステントは静かに解放され、ページファイルは以前のサイズと割り当てに戻ります。再びそうです。
したがって、ページファイルの展開を許可すると、完全に無料のセーフティネットとして機能します。許可しても、システムがそれを必要としない場合、システムは「ページファイルを絶えず拡大および縮小」しません。また、必要な場合は、「仮想メモリ不足」エラーでアプリがクラッシュするのを防ぎます。
しかし、しかし...
多数のWebサイトで、ページファイルの展開を許可すると、Windowsは常にページファイルを展開および縮小し、デフラグするまでページファイルが断片化することを読みました。
彼らはただ間違っています。
「メモリ不足」(または古いバージョンでは「仮想メモリ不足」)ポップアップが表示されたことがない場合、OSはページファイルを拡張したことがありません。
そのポップアップが表示された場合、初期ページファイルのサイズが小さすぎることがわかります。(最大観測使用量の約4倍に設定するのが好きです。つまり、「%pagefile usage peak」perfmonカウンタは25%未満にする必要があります。プレイする。)
しかし、なぜ彼らは...
OSは割り当てを発生させ、ページフォールトを解決するために利用可能なRAMがなければ参照を失敗させるべきだと主張するかもしれません。言い換えれば、我々は最初のページフォルトの作品は、何があれば利用可能ではなかった、ので、(ステップ1)を行うことができませんでした「RAMの使用可能な物理ページを割り当て、」どのように説明したところ上記のアップとない場所がありませんでした利用できるようにするために何かをページに残しましたか?
その後、ページャーはページフォールトを解決できません。例外(ページフォールト)がフォールトしているスレッドに報告され、おそらく他の例外コードに変更されるようにする必要があります。
設計理念は、コミット制限を超えた場合、VirtualAllocはアドレスの代わりにゼロ(技術的にはNULLポインター)を返すことであり、VirtualAlloc呼び出しが失敗する可能性があることをプログラマーに知らせることはまったく合理的です。そのため、プログラマーはそのケースをチェックし、それに応じて合理的なことを行うことが期待されます(その時点まで作業を保存し、「優雅に」プログラムを終了する機会を与えるなど)。(プログラマー:malloc、newなどからNULLポインターが返ってくるかどうかを確認します、そうですか?それなら、なぜそうしないのですか?)
ただし、プログラマは、次のような単純なメモリ参照を期待する必要はありません。
i = 0; // initialize loop counter
失敗する可能性があります-正常にコミットされたアドレス空間の領域にある場合ではありません。(または、そのことについては、マップされたアドレス空間。)しかし、それは「オーバーコミットされた割り当てを許可し、メモリ参照を失敗させる」という哲学に従った場合に起こり得ることです。
残念ながら、上記のコード行にあるようなメモリ参照には、悪いステータスを返す便利な方法がありません!彼らはちょうどことになっている作品だけ加算と減算のように、。このような失敗を報告する唯一の方法は、例外としてです。したがって、それらを処理するには、プログラマーはプログラム全体を例外ハンドラーでラップする必要があります。(…catchを試してみてください。)
それはできます...しかし、ハンドラーは、例外が発生する可能性のあるコードに非常に多くのポイントがあるため、それらの例外に応じて「正しいことを行う」方法を知ることは困難です。(具体的には、彼らがで発生する可能性があるすべてのスタックがあまりにVirtualAlloc'dされているので、同様のmallocやnewで割り当てられたメモリへ...と、すべてのローカル変数に、VirtualAlloc'dメモリへのメモリ参照。)
つまり、これらの場合にプログラムを正常に失敗させることは非常に困難です。
一方、VirtualAlloc(または、mallocまたはnewから返されたNULLポインターを確認するのは簡単です)その仮想空間を必要とするプログラムが何であれ、それを実行します。そして、もしあれば、今までの作業を保存するかどうかをユーザーに尋ねます。(確かに、あまりにも多くのアプリがそれほど多くのことをしません。)
コミットの他のユーザー
ちなみに、「コミット制限」は、ページプールや非ページプール、PFNリストなど、OSのさまざまな割り当てによって削減されることはありません。これらは発生したときに充電をコミットするために課金されます。また、ビデオRAM、さらにはビデオRAMの「ウィンドウ」サイズの影響を受けるコミットチャージまたはコミット制限もありません。
自分でテストする
SysInternalsサイトのtestlimitツールを使用して、これらすべてをデモできます。オプション-mは、コミットされたアドレス空間を割り当てますが、「タッチ」しないため、RAMの割り当ては発生しません。一方、オプション-dはページを割り当てて参照するため、コミットチャージが増加し、使用可能なRAMが減少します。
参照資料
Russinovich、Solomon、およびIonescuによるWindows Internals。testlimitツールを使用して、これらすべてのポイントを証明できるデモもあります。ただし、これが長いと思われる場合は注意してください。Mmの章だけでも200ページです。上記は非常に単純化されたバージョンです。(はじめにの「謝辞」セクションもご覧ください。)
MSDN VirtualAllocのドキュメントも参照してください