OSX では、Activity Monitor が実際に非常に適切な推測を提供します。
プライベート メモリは、アプリケーションによってのみ使用される確実なメモリです。たとえば、スタック メモリと、malloc() および同等の関数/メソッド (Objective-C の alloc メソッド) を使用して動的に予約されるすべてのメモリは、プライベート メモリです。フォークすると、プライベート メモリが子と共有されますが、コピー オン ライトとマークされます。つまり、ページがどちらのプロセス (親または子) によっても変更されない限り、ページはそれらの間で共有されます。いずれかのプロセスがいずれかのページを変更するとすぐに、このページは変更される前にコピーされます。このメモリは fork の子と共有されますが (fork の子とのみ共有できます)、「プライベート」メモリとして表示されます。最悪の場合、そのすべてのページが (遅かれ早かれ) 変更され、その後、再び各プロセスに対してプライベートになります。
共有メモリとは、現在共有されているメモリ (異なるプロセスの仮想プロセス空間で同じページが表示される) か、将来共有される可能性があるメモリ (たとえば、読み取りを共有しない理由がないため、読み取り専用メモリ) のいずれかです。 -メモリのみ)。少なくとも、Apple のいくつかのコマンド ライン ツールのソース コードを読む方法はこれです。したがって、mmap (または同じメモリを複数のプロセスにマップする同等の呼び出し) を使用してプロセス間でメモリを共有する場合、これは共有メモリになります。ただし、アプリケーションの別のインスタンスが開始された場合、既にメモリにロードされているコードを共有しない理由がないため、実行可能コード自体も共有メモリです (実行可能コード ページはデフォルトで読み取り専用です。アプリをデバッガーで)。したがって、共有メモリは実際にはアプリケーションが使用するメモリです。
実メモリは、プライベートか共有かに関係なく、現在プロセスに「割り当てられている」RAM の量です。これは、プライベートと共有の合計になる可能性がありますが、通常はそうではありません。プロセスには、現在必要なよりも多くのメモリが割り当てられている可能性があります (これにより、将来のメモリの追加要求が高速化されます) が、システムにとっては損失ではありません。別のプロセスがメモリを必要としていて空きメモリが利用できない場合、システムがスワッピングを開始する前に、その余分なメモリがプロセスから取り除かれ、別のプロセスが割り当てられます (これは高速で簡単な操作です)。そのため、次の malloc 呼び出しは多少遅くなる可能性があります。実メモリは、プライベート メモリや物理メモリよりも小さい場合もあります。これは、プロセスがシステムからメモリを要求した場合、「仮想メモリ」のみを受け取るためです。この仮想メモリは、使用しない限り、実際のメモリ ページにはリンクされません (したがって、10 MB のメモリを malloc し、その 1 バイトのみを使用すると、プロセスは割り当てられたメモリの 4096 バイトの 1 ページのみを取得します。 -残りは実際に必要な場合にのみ割り当てられます)。さらにスワップされたメモリは、実際のメモリにはカウントされない場合がありますが (これについては不明です)、共有メモリとプライベート メモリにはカウントされます。
仮想メモリは、アプリのプロセス空間で有効と見なされるすべてのアドレス ブロックの合計です。これらのアドレスは、物理メモリ (これもプライベートまたは共有) にリンクされている場合とリンクされていない場合がありますが、その場合、アドレスを使用するとすぐに物理メモリにリンクされます。既知のアドレス以外のメモリ アドレスにアクセスすると、SIGBUS が発生し、アプリがクラッシュします。メモリがスワップされると、このメモリの仮想アドレス空間は有効なままになり、それらのアドレスにアクセスするとメモリがスワップインされます。
結論:
アプリが明示的または暗黙的に共有メモリを使用しない場合、プライベート メモリは、スタック サイズ (またはマルチスレッドの場合はサイズ) と、動的メモリに対して行った malloc() 呼び出しのために、アプリが必要とするメモリの量です。その場合、共有メモリまたは実メモリをあまり気にする必要はありません。
アプリが共有メモリを使用していて、これにグラフィカル UI が含まれている場合、たとえばアプリケーションと WindowServer の間でメモリが共有されている場合は、共有メモリも確認できます。共有メモリの数値が非常に高い場合は、現時点でメモリにロードされているグラフィック リソースが多すぎることを意味している可能性があります。
アプリ開発では、実際のメモリはほとんど重要ではありません。共有とプライベートの合計よりも大きい場合、これは、システムがプロセスからメモリを奪うことを怠っていることを意味します。小さい場合は、プロセスが実際に必要とするよりも多くのメモリを要求していますが、これも悪いことではありません。要求されたメモリをすべて使用しない限り、システムからメモリを「盗む」ことにはならないからです。共有とプライベートの合計よりもはるかに小さい場合は、メモリを少し過剰に要求しているため、可能な限り少ないメモリを要求することのみを検討できます (繰り返しますが、これは悪くありませんが、コードがそうではないことがわかります)。メモリ使用量を最小限に抑えるように最適化されており、クロスプラットフォームの場合、他のプラットフォームにはそのような洗練されたメモリ処理がない可能性があります。
これらすべての情報にまだ満足できない場合は、さらに多くの情報を入手できます。ターミナルを開き、次を実行します。
sudo vmmap <pid>
はプロセスのプロセス ID です。これにより、プロセス空間内のメモリのすべてのブロックの統計が、開始アドレスと終了アドレスとともに表示されます。また、このメモリがどこから来たのか (マップされたファイル? スタック メモリ? Malloc されたメモリ? 実行可能ファイルの __DATA または __TEXT セクション?)、サイズ (KB)、アクセス権、プライベートかどうかもわかります。共有またはコピーオンライト。ファイルからマップされている場合は、ファイルへのパスも提供されます。
「実際の」RAM使用量のみが必要な場合は、使用します
sudo vmmap -resident <pid>
これで、すべてのメモリ ブロックについて、メモリ ブロックが仮想的にどのくらいの大きさで、実際に物理メモリにどれだけ存在するかが表示されます。
各ダンプの最後には、さまざまなメモリ タイプの合計を示す概要表もあります。この表は、現在私のシステムの Firefox では次のようになっています。
REGION TYPE [ VIRTUAL/RESIDENT]
=========== [ =======/========]
ATS (font support) [ 33.8M/ 2496K]
CG backing stores [ 5588K/ 5460K]
CG image [ 20K/ 20K]
CG raster data [ 576K/ 576K]
CG shared images [ 2572K/ 2404K]
Carbon [ 1516K/ 1516K]
CoreGraphics [ 8K/ 8K]
IOKit [ 256.0M/ 0K]
MALLOC [ 256.9M/ 247.2M]
Memory tag=240 [ 4K/ 4K]
Memory tag=242 [ 12K/ 12K]
Memory tag=243 [ 8K/ 8K]
Memory tag=249 [ 156K/ 76K]
STACK GUARD [ 101.2M/ 9908K]
Stack [ 14.0M/ 248K]
VM_ALLOCATE [ 25.9M/ 25.6M]
__DATA [ 6752K/ 3808K]
__DATA/__OBJC [ 28K/ 28K]
__IMAGE [ 1240K/ 112K]
__IMPORT [ 104K/ 104K]
__LINKEDIT [ 30.7M/ 3184K]
__OBJC [ 1388K/ 1336K]
__OBJC/__DATA [ 72K/ 72K]
__PAGEZERO [ 4K/ 0K]
__TEXT [ 108.6M/ 63.5M]
__UNICODE [ 536K/ 512K]
mapped file [ 118.8M/ 50.8M]
shared memory [ 300K/ 276K]
shared pmap [ 6396K/ 3120K]
これは何を教えてくれますか?たとえば、Firefox バイナリとそれがロードするすべてのライブラリには、__TEXT セクションに 108 MB のデータがありますが、現在メモリに常駐しているのはそのうちの 63 MB だけです。フォント サポート (ATS) には 33 MB が必要ですが、実際にメモリにあるのは約 2.5 MB だけです。5 MB を少し超える CG バッキング ストア (CG = コア グラフィックス) を使用します。これらは、高速描画のためにキャッシュされるウィンドウ コンテンツ、ボタン、画像、およびその他のデータである可能性が高くなります。malloc 呼び出しを介して 256 MB を要求し、現在 247 MB が実際にメモリ ページにマップされています。スタック用に 14 MB のスペースが確保されていますが、現在実際に使用されているのは 248 KB のスタック スペースのみです。
vmmap には、表の上にも適切な要約があります
ReadOnly portion of Libraries: Total=139.3M resident=66.6M(48%) swapped_out_or_unallocated=72.7M(52%)
Writable regions: Total=595.4M written=201.8M(34%) resident=283.1M(48%) swapped_out=0K(0%) unallocated=312.3M(52%)
そして、これは OS X の興味深い側面を示しています。ライブラリから取得される読み取り専用メモリの場合、スワップ アウトされているか、単に割り当てられていない場合、そのメモリは何の役割も果たしません。居住者のみが存在し、居住者は存在しません。書き込み可能なメモリの場合、これは違いを生みます (私の場合、要求されたすべてのメモリの 52% が使用されておらず、割り当てられていないため、メモリの 0% がディスクにスワップアウトされています)。
その理由は単純です。マップされたファイルからの読み取り専用メモリはスワップされません。システムがメモリを必要とする場合、メモリはすでに「スワップ」されているため、現在のページは単にプロセスから削除されます。ファイルから直接マップされたコンテンツのみで構成され、ファイルがまだ存在するため、このコンテンツは必要に応じていつでも再マップできます。そうすれば、このメモリがスワップ ファイルのスペースを浪費することもありません。ファイルのコンテンツは以前にディスクに保存されていなかったため、書き込み可能なメモリのみを、削除する前にファイルにスワップする必要があります。