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

我正在开发一个当前有数百个对象创build的应用程序。

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

你可以使用像内存分析器

.NET内存分析器( http://memprofiler.com/

要么

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

一个粗略的方法可能是这种情况下,你想知道什么事情发生在一个特定的对象

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

希望这可以帮助 ;)

ant内存分析器会告诉你到底有多less分配给每个对象/方法/等。

这里有一个相关的post ,我们讨论了确定引用types的大小。

你也可以使用WinDbg和SOS或者SOSEX(像SOS一样有更多的命令和一些现有的改进)WinDbg扩展。 您将用于分析特定内存地址处的对象的命令是!objsize

一个非常重要的事情要记住的是!!objsize只给你这个类的大小本身,并不一定包含在类中包含的聚合对象的大小 – 我不知道为什么它不这样做,因为它是相当有时令人沮丧和误导。

我在Connect网站上创build了两个functionbuild议,要求将这个function包含在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

编辑:我添加以下来澄清查尔斯Bretana提供的答案中的一些信息:

  1. OP询问了“对象”而不是“类”的大小。 一个对象是一个类的一个实例。 也许这就是你的意思?
  2. 分配给对象的内存不包含JITted代码。 JIT代码位于自己的“JIT代码堆”中。
  3. JIT只是按方法编译代码,而不是在课堂上。 所以如果一个方法永远不会被调用一个类,它永远不会被JIT编译,因此从来没有在JIT代码堆上为它分配内存。

顺便说一下,CLR使用了大约8种不同的堆:

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

HTH

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

 !dumpheap -stat 

请注意,!dumpheap只给出对象types本身的字节,并不包含它可能引用的任何其他对象types的字节。

如果要查看特定对象types的总保留字节数(将您的对象引用的所有对象的所有字节总和),请使用像Trace Trace这样的内存分析器 – http://www.jetbrains.com/profiler/

每个“类”都需要足够的内存来存放运行时调用的所有成员的所有jit编译代码(尽pipe如果不调用一段时间的方法,CLR可以释放内存,如果再次调用它,再重新debugging一次…加上足够的内存来容纳在类中声明的所有静态variables…但是这个内存只能在每个类中分配一次,无论您创build的类有多less个实例。

对于您创build的类的每个实例(并没有收集垃圾),您可以通过将每个基于实例的声明variables的内存使用量相加来近似内存占用量(字段)

引用variables(引用其他对象)需要4或8字节(32/64位OS?)int16,Int32,Int64分别采取2,4或8字节…

stringvariables需要额外的存储一些元数据元素,(加上地址指针的大小)

另外,对象中的每个引用variables也可以被认为是“间接”包含它指向的对象在堆上占用的内存,尽pipe您可能想要将该内存计算为属于该对象的variables引用它…

等等

如果可以的话 – 序列化它!

 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 

在运行时什么大小的学术问题 这很有趣,但只能通过与正在运行的进程相关的分析器来正确回答。 我最近花了一段时间看这个,确定没有一个通用的方法是准确和快速的,以至于你想在生产系统中使用它。 像数组types的简单情况下有简单的答案,但除此之外,最好的答案是不要试图解决它。 你为什么想知道这个? 是否还有其他可用于相同目的的信息?

在我的情况下,我最终想要回答这个问题,因为我有各种有用的数据,但可以丢弃,以释放RAM的更关键的服务。 这里的海报男孩是一个撤消堆栈和一个caching

最后我得出结论:pipe理撤销堆栈和caching大小的正确方法是查询可用内存量(这是一个64位进程,因此可以安全地假设它是全部可用的),然后允许更多的项目如果有足够大的RAM缓冲区,并且要求在RAM运行低时需要删除项目,则需要添加。