VMMap を使用して、混合モード (マネージドおよびアンマネージド) アプリケーションでの仮想/プロセス アドレス空間の使用率を分析しています。Windows VMM と仮想メモリ API のしくみ、ヒープ メモリ API のしくみも理解しています。私が使用している CRT の実装を (詳細ではありませんが) 見て、(これは私の失敗かもしれませんが) 前述の Win32 API がどのように使用されるかを理解しています。
この「プライベートデータ」統計が私に何を示しているのかを理解しようとしています。私のアプリケーションは、Win32 メモリ API 関数を直接呼び出すことはなく、ネイティブ C++ では「malloc/new」、C# では「new」のみを使用します (これは、Win32 メモリ管理 API を使用します)。
VMMap による「プライベート データ」の定義は次のとおりです。
プライベート メモリは、VirtualAlloc によって割り当てられるメモリであり、ヒープ マネージャまたは .NET ランタイムによってサブ割り当てされることはありません。他のプロセスと共有することはできず、システムのコミット制限に対して課金され、通常はアプリケーション データが含まれます。
この定義から、VirtualAlloc を呼び出しているのは誰でしょうか? それはヒープ マネージャーですか、それとも .Net ランタイムですか?
コミットされたプライベート データのいくつかのアドレスを取得し、WinDbg を使用して調べることができました....まあ... Microsoft は彼らの知恵で ntdll パブリック シンボルを無効にしたことが判明したため、WinDbg はうまく機能しません - 私は要求があれば、これに関する詳細を提供できますが、基本的に !address -summary などのコマンドは、シンボルが見つからないために機能しなくなります。
この質問を別の言い方をすると、次のようになります。このプライベート データ統計を増加または減少させる C++ または C# コードを記述できますか? それとも、これはすべて OS、C++ ランタイム、または .Net ランタイムによって管理されているので、気まぐれに翻弄されているのでしょうか?
VMMap の性質 (他のメモリ タイプは排他的) から、この「プライベート データ」は次のタイプのアドレス空間のいずれにもなりえないと推測できます。
- ヒープ (これには、上記のプライベート データの説明で説明したように、VirtualAlloc の呼び出しによって予約された、コミットされたヒープ領域と予約されたヒープ領域が含まれることに注意してください)。
- マネージド ヒープ
- スタック
- 共有可能
- マップされたファイル
- 画像
- ページテーブル
- 使用不可
- 無料
(VMMap が上記のすべてのタイプと見なすものを定義するオンライン ヘルプ ファイルは見つかりませんでしたが、ヘルプ ファイルをダウンロードするためのリンクは次のとおりです: https://technet.microsoft.com/en-us/library/dd535533.aspx )
私のアプリケーションでは、ヒープ/マネージド ヒープ/スタックのサイズが予想どおりに変化しているにもかかわらず、プライベート データの合計 (予約済みおよびコミット済み) サイズが、アプリケーションの有効期間を通じてほぼ一定のままであることに気付きました。また、プライベート データで使用される合計 250Mb のうち、実際にコミットされているのは 33Mb のみであることにも気付きました。これを測定する私の方法はかなり初歩的であるため、測定ごとに値が変化している可能性があり、それが表示されていないことに注意してください(これが何を測定しているかを知っていれば、DebugDiagを使用してプロセスのダンプを取得できます関連するカウンターが特定のしきい値に達した場合 (ニワトリとエッグ)。
私の現在の投機的理論は、これは、ネイティブ (または管理されていると思いますか?) ヒープが容量に達したときに成長するために予約されているスペースであるというものですが、これを証明するものは何もありません。そのため、投機的な山にしっかりと残っています。
これに関する詳細をインターネットで検索するのは骨が折れる場合があります。多くの投稿/記事/ブログがあり、物事を混乱させ、自己参照定義を使用しています (パフォーマンス モニターのワーキング セットの定義の最初の文は、この良い例です)。不完全であるか、単に間違っています。多くの場所で、定義があいまいになったり、一貫性のない用語が使用されたりします (フィールドのプライベート データの VMMaps 定義は、それをプライベート メモリと呼んでいることに注意してください。おそらく、多少の不満がありますが、あいまいです)。
インターネットの残りの部分が混乱して不正確になっていることを批判したので...上記に意味をなさないものがある場合、または反対のドキュメントを表示できる場合、またはより明確な定義が必要な場合、私に知らせてください、私も犯罪者リストに入れます!オンラインで誰かに記憶の問題を説明しようとすることの前半は、全員が同じことについて話していることを確認することだと思います.
最後に、この質問: VMMap は特定のメモリ領域がスレッド スタックであることを具体的にどのように認識しますか? 答えが見つからない可能性があることを示唆しています:/
更新/編集: gflags ユーザー スタック トレース (gflags -i myapp.exe +ust) をオンにすると、プライベート データのサイズを増やすことができることがわかりました。これはバックトレース データベースであると想定しますが、gflags がなくても存在します、私が説明するのに苦労しているプライベートデータがまだあります。