【发布时间】:2008-09-30 20:46:29
【问题描述】:
在 .NET 中找出对象使用多少内存的最简单方法是什么?
最好不必求助于第三方工具。 Marshal.SizeOf 或 sizeof 运算符看起来很有用,但仅适用于有限范围的类型。
一些相关的帖子:
【问题讨论】:
在 .NET 中找出对象使用多少内存的最简单方法是什么?
最好不必求助于第三方工具。 Marshal.SizeOf 或 sizeof 运算符看起来很有用,但仅适用于有限范围的类型。
一些相关的帖子:
【问题讨论】:
在这里提问和回答:Determine how much memory a class uses?
快速总结一下,如果你不想使用工具,你需要使用.NET Profiling API
Profiling API 非常强大,但我不认为它会被认为是“简单”的,所以我强烈建议使用内存分析工具 - 有一些免费的工具是可以的,以及一些不太昂贵的商业广告(尤其是JetBrains dotTrace),它们真的很棒。
【讨论】:
你也可以这样做:
int startMem = GC.GetTotalMemory(true);
YourClass c = new YourClass();
int endMem = GC.GetTotalMemory(true);
int usedMeme = endMem - startMem;
【讨论】:
由于 .NET 的垃圾收集特性,测量实际使用了多少内存有点困难。例如,如果你想测量一个类实例的大小,它是否包括你的实例所指向的实例所使用的内存?
如果答案是否定的,将所有字段的大小相加: 使用反射,遍历类的所有成员;将 Marshal.Sizeof(member.Type) 用于 typeof(ValueType).IsAssignableFrom(member.Type) 的任何内容 - 这测量原始类型和结构,所有这些都驻留在类的实例分配中。每个引用类型(任何不能分配给值类型的)都将采用 IntPtr.Size。有很多令人作呕的例外,但它可能对你有用。
如果答案是肯定的,那么您有一个严重的问题。多个事物可以引用一个实例,因此如果“a”和“b”都指向“c”,则RecursiveSizeOf(a) + RecursiveSizeOf(b) 将大于SimpleSizeOf(a) + SimpleSizeOf(b) + SimpleSizeOf(c)。
更糟糕的是,递归测量可能会导致您向下循环引用,或者导致您不打算测量的对象 - 例如,如果一个类正在引用互斥锁,则该互斥锁可能指向拥有它的线程。该线程可能指向它的所有局部变量,这些局部变量指向一些 C# 框架结构......您最终可能会测量整个程序。
理解像 C# 这样的垃圾收集语言在区分对象和内存单元的方式上有点“模糊”(从完全非技术意义上说)可能会有所帮助。这是Marshal 减轻的很多内容 - 封送规则确保您正在封送(或测量)的结构具有明确定义的内存布局,因此具有明确定义的大小。在这种情况下,如果您打算使用 Marhsal.SizeOf(),则应该使用定义明确、可编组的结构。
另一个选项是序列化。这不会具体告诉您正在使用多少内存,但它会让您对对象的大小有一个相对的了解。但同样,为了对事物进行序列化,它们必须具有明确定义的布局(因此也必须具有明确定义的大小)——您可以通过使类适当地可序列化来完成。
如果上述任何选项对您有吸引力,我可以发布实施示例。
【讨论】: