web-dev-qa-db-ja.com

C#/。NETオブジェクトはどのくらいのメモリを使用しますか?

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

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

51
FerranB

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

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

または

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

39
Rauhotz

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

// 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;

お役に立てれば ;)

37
varun

ANTSメモリプロファイラ は、各オブジェクト/メソッド/などに割り当てられている正確な量を示します。

11
George Stocker

関連記事はこちら 参照型のサイズの決定について説明しました。

10
John Sheehan

また、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

EDIT:以下を追加して、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

7
Dave Black

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

!dumpheap -stat

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

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

6
Sean

各「クラス」は、ランタイムによって呼び出されたすべてのメンバーのすべてのjitコンパイル済みコードを保持するために十分なメモリを必要とします(ただし、そうしない場合、メソッドをかなり長い間呼び出さず、CLRはそのメモリを解放し、再度呼び出した場合は、再度書き直してください...さらに、クラスで宣言されたすべての静的変数を保持するのに十分なメモリ...

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

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

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

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

などなど.

6
Charles Bretana

可能であれば-シリアル化してください!

Dim myObjectSize As Long

Dim ms As New IO.MemoryStream
Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
bf.Serialize(ms, myObject)
myObjectSize = ms.Position
5
serhio

)実行時のオブジェクトのサイズは何ですか?それは興味深いですが、できるのは実行中のプロセスに接続されているプロファイラーによって適切に回答されます。私は最近これを見てかなり時間を費やし、本番システムで使用したいと思うほど正確で高速な汎用メソッドはないと判断しました。数値型の配列のような単純なケースには簡単な答えがありますが、これ以上のベストアンサーはそれを解決しようとしないでください。なぜこれを知りたいですか?同じ目的に役立つ他の情報はありますか?

私の場合、有用なさまざまなデータがあったためにこの質問に答えたいと思いましたが、より重要なサービスのためにRAM。 スタックの取り消しおよびキャッシュ

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

1
briantyler