4

私がWindowsでC++を使用して構築しているサーバーアプリケーションは、仮想サイズが約2GBに達するとメモリが不足します(32ビットアプリケーション、ラージアドレス対応が有効になっています)。ただし、プライベートバイトはかなり小さいことに気付きました。現在の統計は次のとおりです。

仮想サイズ:2.6GBプライベートバイト:1.6GB

これら2つの数値の違いは1GBです。だから私の質問は:

  1. この1GBの違いは何を表していますか?
  2. 仮想サイズまたはプライベートバイトが原因でアプリケーションのメモリが不足していませんか?

また、VMMapユーティリティを使用してアプリケーションを実行しましたが、「プライベートデータ」は通常、コミットされたサイズよりも1桁大きいことに気付きました。つまり、プライベートデータの合計サイズは200MBになる可能性がありますが、コミットされたサイズはわずか20MBです。プライベートデータが何であるかはよくわかりませんが、これまでの私の調査によると、それはヒープの一部にすぎないことを示しているようです。

編集:

Purifyを使用してメモリリークを探しましたが、実際には何も役に立ちませんでした。ポインタのないメモリという形でのメモリリークは問題ではないようですが、メモリが長時間保持されているという点でのメモリリークが問題になる可能性があります。まだ調べていません。ただし、重要なのは、仮想サイズがメモリ不足の問題を引き起こしている理由を理解することです。質問1は私がこれを理解するために最も重要です。

4

4 に答える 4

6

これには少し説明が必要になるので、ここで私に固執してください。

まず、このトピックは矛盾する用語の紛らわしい泥沼です。したがって、「仮想メモリ」がディスクと関係があるという考えをすべて捨ててください。

  • 物理メモリは、物理デバイスに保存されているメモリです。これは通常、システムRAMを指しますが、ディスクバッファ、NICバッファ、グラフィックカードVRAMなどの場合もあります。
  • 仮想メモリは、ユーザーモード(仮想)アドレス範囲にマップされた物理アドレス範囲のセットであり、メモリに安全かつ区画化された方法でアクセスできるようにします。

これを行う理由について簡単に説明します。プロセスに直接メモリアドレスを指定した場合、(実現可能に)単一のメモリストアしか持てませんでした。これは不便であり、パフォーマンスに悪影響を及ぼします。仮想アドレスがシステムメモリ(RAM)の範囲外の物理アドレスに変換されると、プロセッサはページフォールトを発行します。これは、OSの割り込みハンドラーに信号を送り、OSの割り込みハンドラーはメモリアクセス操作を別のデバイスに委任できます。使える!

32ビットWindowsシステムでは、プロセスが任意の時点でアドレス指定できる仮想メモリの最大量は2GBです。これは、AWEを使用して3GBに、またはAWEを使用して4GBに増やすことができます/4GT。これは、プロセスが2GB(または前述の設定によっては3GB / 4GB)のメモリしか割り当てることができないという意味ではありません。それ以上に同時にアクセスできないことを意味します。

たとえば、サイズが1GBのメモリマップトファイルを開くと、仮想メモリの使用量が1GB増加します。RAMにもディスクにも触れていませんが、プロセスに仮想アドレス空間のブロックを割り当てています。このメモリマップトファイルを使用可能にすると同時に1.1GBのRAMを割り当てたい場合は、できません。まず、プロセスからファイルのマップを解除する必要があります。メモリは割り当てられたままでデータでいっぱいになる可能性がありますが、実際にはプロセスにマップされないことに注意してください。マシンに8GBのRAMがある場合は、6GBのRAMをデータで埋めて、2GBをプロセスにマップできます。そのメモリの別のセクションを使用する必要がある場合は、既存のブロックのマップを解除し、他のセクションをマップする必要があります。

だから、あなたが見ている違いに:

  1. プライベートバイトは、他のプロセス(マップされたファイル、グローバルヒープなど)と共有されている仮想メモリを除いて、プロセスがマップした仮想デバイスメモリのバイト数を示します。

  2. ワーキングセットは、アクティブに使用している物理メモリのバイト数を示します。これには、物理​​メモリ、デバイスバッファ、およびマップされたファイルが含まれます。これは、タッチされた物理メモリ+マップされた仮想非システムメモリに相当するため、かなり奇妙な数字です。一般に、この数字は完全に無視する必要があります。メモリリークのデバッグには実質的に役に立ちません。

  3. 仮想バイトは、マップした仮想メモリの合計量です。

違いは、共有仮想メモリ(DLLファイルの束やグローバルヒープのブロックなど)をプロセスにマップしたことです。この違いは、これらの共有マッピングの合計サイズが約1GBであることを示しています。

これは、高速システムリソース(RAM)の可用性を高めるためにシステムメモリページをディスク(いわゆる「ページファイル」)に転送するスワッピングとは何の関係もないことに注意してください。そのファイルの名前は、Windowsのこの領域で混乱を招きませんでした。マイクロソフトが最終的に、「仮想メモリ」や「ページファイル」ではなく「スワップ」と呼ぶことにしたとき、私は大喜びします。

于 2012-07-02T15:45:24.787 に答える
2
  1. 仮想サイズとプライベートバイトの説明:プライベートバイト、仮想バイト、ワーキングセットとは何ですか?(以下の引用を参照)
  2. アプリケーションは、特に2GBで仮想サイズの制限に達する可能性があります。あなたは自分でそのような行動を見ているので
  3. /LARGEADDRESSAWAREシステム自体が/3GBAKA 4GTを有効Win32にして起動した場合にのみ、オペレーティングシステムのアプリケーションの仮想サイズ制限を拡張します

仮想バイトは、プロセス全体が占める仮想アドレス空間の合計です。これは、メモリマップトファイル(共有DLL)が含まれているという意味でワーキングセットに似ていますが、スタンバイリストのデータと、すでにページアウトされてディスク上のページファイルのどこかにあるデータも含まれています。負荷の高いシステムのすべてのプロセスで使用される仮想バイトの合計は、マシンが実際に持っているよりも大幅に多くのメモリになります。

したがって、関係は次のとおりです。

  • プライベートバイトはアプリが実際に割り当てたものですが、ページファイルの使用量が含まれます。
  • ワーキングセットは、ページングされていないプライベートバイトとメモリマップトファイルです。
  • 仮想バイトは、ワーキングセットに加えてページングされたプライベートバイトとスタンバイリストです。
于 2012-07-02T15:31:35.247 に答える
1

私のマシンでも同様の問題が発生し、C / C++/。NETwin32アプリケーションのメモリが不足していました。2GBの仮想アドレスをすべて消費しました。Process Explorerがアプリケーションによって使用された約900MBのメモリしか表示しなかったため、仮想アドレスの枯渇のように見えました。VMMapは、1.6GBのプライベートデータと約700MBのコミットされていないメモリを示しました。

その理由は単純なものではありませんでした。アプリケーションをテストするように構成されたアプリケーションベリファイア(C:\ Windows \ SysWOW64 \ appverif.exe)(基本的なテストは-vfbasics.dllとマークされています)。アプリケーションベリファイアからアプリケーションを削除した後、正常に機能しました。

于 2014-11-07T16:07:17.953 に答える
0

コメント:ラージアドレスアウェアを有効にすると、OSは、特定の実行可能ファイルから作成されたプロセスの仮想アドレス空間を、通常の2:2ではなく3:1の方法で安全に分割できることを通知するだけです。アプリケーションが3:1分割をサポートしていることを明示的に識別する必要がある理由はさまざまですが、最も明白な理由は、2:2モードで、仮想アドレスのMSBをプローブして、アドレスがカーネル部分に属しているかどうかをテストできることです。仮想アドレス空間またはユーザー部分への。3:1では、MSBも有効であるため、このテストは無効になります。1仮想アドレス空間のユーザー部分の1/3。これには、このアプリケーションが呼び出す可能性のあるドライバーも3:1分割の可能性を認識し、別の方法を使用して、特定の仮想アドレスがnotのユーザースペースに属しているかどうかをテストする必要があります。

Roman R.が指摘しているように、3:1VAスペース分割のサポートを有効にするようにカーネルに明示的に指示する必要があります。

于 2012-07-02T15:49:21.203 に答える