55

現在、何百ものオブジェクトが作成されているアプリケーションを開発しています。

オブジェクト (クラス インスタンス) によって割り当てられたメモリを決定 (または概算) することは可能ですか?

4

10 に答える 10

40

次のようなメモリプロファイラーを使用できます

.NET メモリ プロファイラー ( http://memprofiler.com/ )

また

CLR プロファイラー (無料) ( http://clrprofiler.codeplex.com/ )

于 2009-01-08T23:05:58.613 に答える
40

特定のオブジェクトで何が起こっているかを知りたい場合に備えて、大まかな方法​​はこれです

// Measure starting point memory use
GC_MemoryStart = System.GC.GetTotalMemory(true);

// Allocate a new byte array of 20000 elements (about 20000 bytes)
MyByteArray = new byte[20000];

// Obtain measurements after creating the new byte[]
GC_MemoryEnd = System.GC.GetTotalMemory(true);

// Ensure that the Array stays in memory and doesn't get optimized away
GC.KeepAlive(MyByteArray);

プロセス全体のものは、おそらくこのように取得できます

long Process_MemoryStart = 0;
Process MyProcess = System.Diagnostics.Process.GetCurrentProcess();
Process_MemoryStart = MyProcess.PrivateMemorySize64;

お役に立てれば ;)

于 2009-04-25T14:49:43.160 に答える
11

ANTSメモリ プロファイラーは、各オブジェクト/メソッド/その他に割り当てられている量を正確に教えてくれます。

于 2009-01-08T23:05:17.053 に答える
10

これは、参照型のサイズの決定について説明した関連記事です。

于 2009-01-08T23:49:00.430 に答える
7

また、WinDbg と SOS または SOSEX のいずれかを使用することもできます (より多くのコマンドといくつかの既存のコマンドが改善された SOS のように) WinDbg 拡張機能。特定のメモリ アドレスにあるオブジェクトを分析するために使用するコマンドは、!objsize です。

覚えておくべき非常に重要な項目の1つは、 !objsize はクラス自体のサイズのみを提供し、クラス内に含まれる集約オブジェクトのサイズを必ずしも含むとは限らないことです.いらいらさせ、時には誤解を招く。

この機能を VisualStudio に含めることを求める 2 つの機能提案を Connect Web サイトで作成しました。追加してほしいアイテムにも投票してください!

https://connect.microsoft.com/VisualStudio/feedback/details/637373/add-feature-to-debugger-to-view-an-objects-memory-footprint-usage

https://connect.microsoft.com/VisualStudio/feedback/details/637376/add-feature-to-debugger-to-view-an-objects-rooted-references

編集: Charles Bretana から提供された回答からの情報を明確にするために、以下を追加します。

  1. OPは「クラス」ではなく「オブジェクト」のサイズについて尋ねました。オブジェクトはクラスのインスタンスです。多分これはあなたが意味したものですか?
  2. オブジェクトに割り当てられたメモリには、JITted コードは含まれません。JIT コードは、独自の「JIT コード ヒープ」に存在します。
  3. JIT は、クラス レベルではなく、メソッドごとにコードをコンパイルするだけです。したがって、メソッドがクラスに対して呼び出されない場合、そのメソッドは JIT コンパイルされないため、JIT コード ヒープでメモリが割り当てられることはありません。

余談ですが、CLR が使用する約 8 つの異なるヒープがあります。

  1. ローダー ヒープ: CLR 構造体と型システムが含まれています
  2. 高頻度ヒープ: statics、MethodTables、FieldDescs、インターフェイス マップ
  3. 低頻度ヒープ: EEClass、ClassLoader、およびルックアップ テーブル
  4. スタブ ヒープ: CAS、COM ラッパー、P/Invoke のスタブ
  5. 大きなオブジェクト ヒープ: 85k バイト以上を必要とするメモリ割り当て
  6. GC ヒープ: アプリ専用のユーザー割り当てヒープ メモリ
  7. JIT コード ヒープ: mscoreee (実行エンジン) によって割り当てられたメモリとマネージ コード用の JIT コンパイラ
  8. プロセス/ベース ヒープ: 相互運用/管理されていない割り当て、ネイティブ メモリなど

HTH

于 2011-03-09T14:02:08.630 に答える
6

各「クラス」には、ランタイムによって呼び出されたすべてのメンバーの jit コンパイルされたコードすべてを保持するのに十分なメモリが必要です (ただし、かなりの時間メソッドを呼び出さない場合、CLR はそのメモリを解放し、もう一度呼び出す場合は、もう一度再起動します...さらに、クラスで宣言されたすべての静的変数を保持するのに十分なメモリ...しかし、このメモリは、作成するクラスのインスタンスの数に関係なく、クラスごとに1回だけ割り当てられます。

作成するクラスの各インスタンス (およびガベージ コレクションされていない) について、各インスタンス ベースの宣言された変数によるメモリ使用量を合計することにより、メモリ フットプリントを概算できます... (フィールド)

参照変数 (他のオブジェクトへの参照) は 4 または 8 バイト (32/64 ビット OS ?) int16、Int32、Int64 はそれぞれ 2、4、または 8 バイトかかります...

文字列変数は、一部のメタデータ要素用に追加のストレージを必要とします (およびアドレス ポインターのサイズ)

さらに、オブジェクト内の各参照変数は、それが指すオブジェクトによってヒープ上で使用されるメモリを「間接的に」含むと見なすこともできます。それを参照します...

などなど

于 2009-01-08T23:08:13.523 に答える
6

アプリケーションでのメモリ割り当ての一般的な意味を理解するには、WinDbg で次の sos コマンドを使用します。

!dumpheap -stat

!dumpheap は、オブジェクト型自体のバイトのみを提供し、それが参照する可能性のある他のオブジェクト型のバイトは含まれないことに注意してください。

特定のオブジェクト タイプの合計保持バイト (オブジェクトによって参照されるすべてのオブジェクトのすべてのバイトの合計) を表示する場合は、ドット トレースのようなメモリ プロファイラーを使用します - http://www.jetbrains.com/profiler/

于 2009-01-09T01:35:21.993 に答える
1

実行時のオブジェクトのサイズは?という学術的な問題があります。これは興味深いことですが、実行中のプロセスに接続されているプロファイラーによってのみ適切に回答できます。私は最近、かなりの時間を費やしてこれを調べましたが、実稼働システムで使用したいと思うほど正確で高速な一般的な方法はないと判断しました。数値型の配列のような単純なケースには簡単な答えがありますが、これを超えると、最善の答えは「わざわざ解決しようとしないでください」です。なぜあなたはこれを知りたいのですか?同じ目的に役立つ他の情報はありますか?

私の場合、有用であるが、より重要なサービスのために RAM を解放するために破棄できるさまざまなデータがあったため、この質問に答えたいと思いました。ここに登場するのはUndo StackCacheです。

最終的に、元に戻すスタックとキャッシュのサイズを管理する正しい方法は、使用可能なメモリの量を照会し (これは 64 ビット プロセスなので、すべて使用可能であると想定しても安全です)、さらに多くの項目を許可することであると結論付けました。 RAM のバッファが十分に大きい場合は追加され、RAM が不足している場合はアイテムを削除する必要があります。

于 2015-12-09T10:08:32.093 に答える