代码之家  ›  专栏  ›  技术社区  ›  scable

对于对象大小估计,序列化是否可靠?

  •  2
  • scable  · 技术社区  · 7 年前

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

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

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

    2 回复  |  直到 17 年前
        1
  •  3
  •   Marc Gravell    17 年前

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

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

    所以你可能会 来自序列化的数字,但它不是 相同的 号码。

    要准确了解对象图的大小是很困难的。SOS可能会有所帮助;否则,创建一个完整的、可卸载的SOS并进行划分。很粗糙,但可能只是起作用。

        2
  •  0
  •   JayMcClellan    17 年前

    这是一个我用来估计托管类型的内存成本的函数。它假定对象在内存中按顺序分配(而不是从大型对象堆中分配),因此它不会为分配大型数组的对象提供准确的结果。它也不能绝对保证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;
    }