C#/ .NET对象使用多少内存?

Fer*_*anB 52 .net c# memory profiling object

我正在开发一个目前创建了数百个对象的应用程序.

是否可以确定(或近似)对象(类实例)分配的内存?

Rau*_*otz 40

您可以使用类似的内存分析器

.NET Memory Profiler(http://memprofiler.com/)

要么

CLR Profiler(免费)(http://clrprofiler.codeplex.com/)


var*_*run 37

粗略的方式可能是这种情况,你想知道特定对象发生了什么

// 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);
Run Code Online (Sandbox Code Playgroud)

可能会像这样获得过程广泛的东西

long Process_MemoryStart = 0;
Process MyProcess = System.Diagnostics.Process.GetCurrentProcess();
Process_MemoryStart = MyProcess.PrivateMemorySize64;
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助 ;)


Geo*_*ker 11

蚂蚁内存分析器会告诉你到底有多少分配给每个对象/方法/等.


Joh*_*han 10

这是一篇相关文章,我们讨论了确定参考类型的大小.


Dav*_*ack 7

您还可以使用WinDbg和SOS或SOSEX(如SOS与更多命令和一些现有的改进)WinDbg扩展.用于分析特定内存地址对象的命令是!objsize

要记住的一个非常重要的项目是!objsize只给出了类本身的大小,并且不一定包括类中包含的聚合对象的大小 - 我不知道它为什么不这样做因为它是相当的有时令人沮丧和误导.

我在Connect网站上创建了2个功能建议,要求将此功能包含在VisualStudio中.请投票支持您希望添加的项目!

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. Loader Heap:包含CLR结构和类型系统
  2. 高频堆:静态,MethodTables,FieldDescs,接口映射
  3. 低频堆:EEClass,ClassLoader和查找表
  4. Stub Heap:CAS,COM包装器,P/Invoke的存根
  5. 大对象堆:需要超过85k字节的内存分配
  6. GC堆:用户分配的堆内存专用于应用程序
  7. JIT代码堆:由mscoreee(执行引擎)分配的内存和托管代码的JIT编译器
  8. 进程/基本堆:互操作/非托管分配,本机内存等

HTH


Cha*_*ana 6

每个"类"都需要足够的内存来保存所有它的运行时调用的所有成员的jit编译代码(尽管如果你不调用方法很长一段时间,CLR可以释放那个内存和如果你再次调用它再次重新启动它...加上足够的内存来保存类中声明的所有静态变量...但是这个内存每个类只分配一次,无论你创建的类的实例数是多少.

对于您创建的类的每个实例(并且尚未收集垃圾),您可以通过将每个基于实例的声明变量的内存使用量相加来近似内存占用量...(字段)

引用变量(引用其他对象)占用4或8个字节(32/64位OS?)int16,Int32,Int64分别取2,4或8个字节...

字符串变量为一些元数据元素占用额外的存储空间(加上地址指针的大小)

此外,对象中的每个引用变量也可以被视为"间接地"包括它指向的对象在堆上占用的内存,尽管您可能希望将该内存计为属于该对象而不是变量引用它......

等等


Sea*_*ean 6

要了解应用程序中内存分配的一般意义,请在WinDbg中使用以下sos命令

!dumpheap -stat
Run Code Online (Sandbox Code Playgroud)

请注意,!dumpheap仅为您提供对象类型本身的字节,并且不包含它可能引用的任何其他对象类型的字节.

如果要查看特定对象类型的总保持字节数(对象引用的所有对象的所有字节数),请使用内存分析器,如点Trace - http://www.jetbrains.com/profiler/


ser*_*hio 5

如果可以 - 序列化它!

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
Run Code Online (Sandbox Code Playgroud)

  • 序列化无助于确定对象的运行时内存开销.例如,可以重新计算的字段不需要序列化.然后各种格式化程序不会开始使用内存转储,因此它只是衡量对象在序列化时的大小,而不是在内存中. (6认同)