在 .NET 中确定复杂对象大小的方法?
Posted
技术标签:
【中文标题】在 .NET 中确定复杂对象大小的方法?【英文标题】:Ways to determine size of complex object in .NET? 【发布时间】:2011-03-04 16:27:11 【问题描述】:有没有办法在 .NET 中确定复杂对象的总大小?该对象由其他对象组成,并且可能包含对其他复杂对象的引用。此对象封装的一些对象可能是 POD,而另一些可能不是。
【问题讨论】:
对象可以序列化吗? 他们可能是 :) 抱歉含糊其辞,但我试图让这个问题尽可能笼统。 什么是 C#/.NET 上下文中的“POD”?这是一个 C++ 术语... @Pavel,是的,POD 是一个 C++ 术语......我使用 POD 来指代 int、string、float、double 等......基本上是 .NET 的 POD 类型......值类型:) 我认为最适合您的意思的 CLR 术语是“blittable 类型”——它是所有原始类型(不包括对象引用)和所有字段本身都是 blittable 类型的结构。 【参考方案1】:试一试System.Runtime.InteropServices.Marshal.SizeOf()
。
【讨论】:
Marshal.SizeOf()
不能考虑子对象的大小。
请记住,这是一个安全关键功能,因此很遗憾在很多情况下都不起作用。
它给出了对象的编组表示的大小,这并不完全相同。【参考方案2】:
棘手...
如果两个对象指向同一个字符串变量怎么办。哪个“拥有”字符串?在我看来,您需要模拟垃圾收集才能获得真正的答案。不是很轻。
【讨论】:
@Paul:不变性与此有什么关系?关键是一个对象可能持有对从外部给它的字符串的引用(例如文件名)。该字符串是否“属于”该对象?它是否应该算作其大小的一部分?【参考方案3】:简单地说,没有办法知道。假设所有对象都是可序列化的,您可以使用 BinaryFormatter 将它们序列化为二进制 blob,然后读取其大小。但是,这将包含一些元数据,并夸大实际对象大小(但这将是一个合理的估计)。
对于值类型,您可以使用Marshal.SizeOf()
,只是它不考虑任何子对象。它会将任何内部引用类型计算为指向它的指针的大小。
反射是另一种方式,但不会暴露任何占用内存的私有成员。所以,除非我弄错了,否则没有办法真正正确地做到这一点。
【讨论】:
【参考方案4】:您拥有的不是“复杂对象”,而是对象图。要确定其总大小,您需要遍历该图 - 从某个根对象开始,并使用反射枚举引用类型的字段并检索它们的值(当然还要检查循环)。
要获取图表中特定对象的大小,请参阅 this answer to a related question,但请注意,这是一个邪恶的 hack,完全不受支持,可能会破坏(并且可能已经破坏),并可能导致大规模的小猫种族灭绝在天界。也就是说,没有“非hacky”的方法来获得精确的值,因为它是定义上的一个实现细节——你不应该对它有任何用处。为了在调试/分析期间找出应用程序的内存使用情况,hack 已经足够了。
【讨论】:
谢谢帕维尔。当我问这个问题时,我理解了复杂性,我只是好奇是否有人已经创建了一个对象图遍历来计算这个:)【参考方案5】:以前在 *** 上的其他地方回答过:
Find size of object instance in bytes in c#
你需要引入不安全的代码(由于这需要指针操作)——代码看起来像这样:
static unsafe int CalcSize(object obj)
RuntimeTypeHandle th = obj.GetType().TypeHandle;
int size = *(*(int**)&th + 1);
return size;
还记得将项目设置(Project->Build 选项卡)标记为“允许不安全代码”。
【讨论】:
以上是关于在 .NET 中确定复杂对象大小的方法?的主要内容,如果未能解决你的问题,请参考以下文章
Visual Studio 监视窗口查看对象的大小/内存占用