【问题标题】:Is Serialization reliable for object size estimation?序列化对于对象大小估计是否可靠?
【发布时间】:2009-04-17 12:33:10
【问题描述】:

我使用序列化来估计一个对象使用的内存量。 我已经读过thisthis。 所以我知道最好使用分析器或 sizeof(对于值类型)。

我想知道,序列化对象和内存中的对象之间的确切区别是什么?序列化在什么方面对对象大小估计是可靠的?

我对 C# 序列化机制特别感兴趣。

【问题讨论】:

  • 二进制序列化还是 XML? XML 将有 /considerable/ 差异,而如果您只是在寻找一般估计,二进制可能或多或少准确。
  • @Spencer - 我认为这两者都不准确......
  • 为什么这是一个社区维基?

标签: c# memory serialization object


【解决方案1】:

数据的序列化形式与内存不同;例如,集合/字典将涉及项目、数组、哈希桶/索引等的多个对象 - 但原始数据(当序列化时)通常只是数据 - 所以你序列化时可能会看到更少的音量。

同样,BinaryFormatter 之类的东西必须包含很多(详细)类型元数据 - 但在对象中,它的对象句柄中只有一个(简洁)类型句柄 - 所以你可能会看到 更多 em> 序列化数据中的数据。同样,序列化程序(除非手动优化)需要标记各个字段 - 但在内存中,这隐含在对象地址的偏移量中。

所以你可能会从序列化中得到一个数字,但它不是相同的数字。

要准确了解对象图的大小是很棘手的。 SOS 可能会有所帮助;否则,创建一个完整的卸载并划分。粗制滥造,但它可能会起作用。

【讨论】:

    【解决方案2】:

    这是我用来估算托管类型的内存成本的函数。它假定对象是在内存中按顺序分配的(而不是从大对象堆中分配的),因此对于分配巨大数组的对象,它不会给出准确的结果。它也不能绝对保证 GC 不会破坏答案,但这不太可能。

    /// <summary>
    /// Gets the memory cost of a reference type.
    /// </summary>
    /// <param name="type">The type for which to get the cost. It must have a
    /// public parameterless constructor.</param>
    /// <returns>The number of bytes occupied by a default-constructed
    /// instance of the reference type, including any sub-objects it creates
    /// during construction. Returns -1 if the type does not have a public
    /// parameterless constructor.</returns>
    public static int MemoryCost(Type type)
    {
      // Make garbage collection very unlikely during the execution of this function
      GC.Collect();
      GC.WaitForPendingFinalizers();
    
      // Get the constructor and invoke it once to run JIT and any initialization code
      ConstructorInfo constr = type.GetConstructor(Type.EmptyTypes);
      if (constr == null)
        return -1;
      object inst1 = constr.Invoke(null); // 
    
      int size;
      unsafe
      {
        // Create marker arrays and an instance of the type
        int[] a1 = new int[1];
        int[] a2 = new int[1];
        object inst2 = constr.Invoke(null);
        int[] a3 = new int[1];
    
        // Compute the size by determining how much was allocated in between
        // the marker arrays.
        fixed (int* p1 = a1)
        {
          fixed (int* p2 = a2)
          {
            fixed (int* p3 = a3)
            {
              size = (int)(((long)p3 - (long)p2) - ((long)p2 - (long)p1));
            }
          }
        }
      }
      return size;
    }
    

    【讨论】:

    • 这里的假设太多了。为什么不使用内存分析器?
    猜你喜欢
    • 2011-02-12
    • 2013-06-11
    • 2011-03-05
    • 1970-01-01
    • 2015-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    相关资源
    最近更新 更多