【问题标题】:Ways to determine size of complex object in .NET?在 .NET 中确定复杂对象大小的方法?
【发布时间】:2023-03-21 23:34:01
【问题描述】:

有没有办法在 .NET 中确定复杂对象的总大小?该对象由其他对象组成,并且可能包含对其他复杂对象的引用。此对象封装的一些对象可能是 POD,而另一些可能不是。

【问题讨论】:

  • 对象可以序列化吗?
  • 他们可能是 :) 抱歉含糊其辞,但我试图让这个问题尽可能笼统。
  • 什么是 C#/.NET 上下文中的“POD”?这是一个 C++ 术语...
  • @Pavel,是的,POD 是一个 C++ 术语......我使用 POD 来指代 int、string、float、double 等......基本上是 .NET 的 POD 类型......值类型:)
  • 我认为最适合您的意思的 CLR 术语是“blittable 类型”——它是所有原始类型(不包括对象引用)和所有字段本身都是 blittable 类型的结构。

标签: c# .net memory memory-management


【解决方案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】:

    以前在 StackOverflow 上的其他地方回答过:

    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 选项卡)标记为“允许不安全代码”。

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 1970-01-01
      相关资源
      最近更新 更多