在 .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 中确定复杂对象大小的方法?的主要内容,如果未能解决你的问题,请参考以下文章

怎么确定Java对象的大小

如何确定 C++ 中对象的大小?

Visual Studio 监视窗口查看对象的大小/内存占用

使用基类指针查找派生类对象的大小

Azure Functions 3.1 .NET Core HttpResponse 在序列化对象上更改大小写

对象创建方法,对象的内存分配,对象的访问定位