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

C# 序列化对于对象大小估计是否可靠?,c#,memory,serialization,object,C#,Memory,Serialization,Object,我使用序列化来估计对象使用的内存量。 我已经读过了,还有。 所以我知道使用分析器或sizeof(用于值类型)可能更好 我想知道,序列化对象和内存中的对象之间的确切区别是什么?序列化对于对象大小估计的可靠性是什么 我对C#序列化机制特别感兴趣。数据的序列化形式与内存中的不同;例如,一个集合/字典将涉及项、数组、哈希桶/索引等的多个对象,但原始数据(序列化时)通常只是数据,因此序列化时可能会看到更少的卷 同样,像BinaryFormatter这样的东西必须包含大量(详细的)类型元数据-但在对象中,它

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

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


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

数据的序列化形式与内存中的不同;例如,一个集合/字典将涉及项、数组、哈希桶/索引等的多个对象,但原始数据(序列化时)通常只是数据,因此序列化时可能会看到更少的卷

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

因此,您可能会从序列化中获得一个数字,但它不是相同的编号


要准确了解对象图的大小是很困难的。SOS可能会有所帮助;否则,创建一个完整的卸载,并进行分割。这是一个我用来估计托管类型内存开销的函数。它假定对象是在内存中按顺序分配的(而不是从大型对象堆中分配的),因此它不会为分配大型数组的对象提供准确的结果。它也不能绝对保证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;
}
//
///获取引用类型的内存开销。
/// 
///要获取成本的类型。它一定有一个
///公共无参数构造函数。
///默认值所占用的字节数
///引用类型的实例,包括它创建的任何子对象
///施工期间。如果类型没有公共值,则返回-1
///无参数构造函数。
公共静态int-MemoryCost(类型)
{
//在执行此函数期间不太可能进行垃圾收集
GC.Collect();
GC.WaitForPendingFinalizers();
//获取构造函数并调用它一次以运行JIT和任何初始化代码
ConstructorInfo constr=type.GetConstructor(type.EmptyTypes);
如果(constr==null)
返回-1;
object inst1=constr.Invoke(null);//
整数大小;
不安全的
{
//创建标记数组和类型的实例
int[]a1=新的int[1];
int[]a2=新的int[1];
object inst2=constr.Invoke(null);
int[]a3=新的int[1];
//通过确定中间分配了多少来计算大小
//标记数组。
固定(int*p1=a1)
{
固定(int*p2=a2)
{
固定(int*p3=a3)
{
大小=(int)((长)p3-(长)p2)-(长)p2-(长)p1));
}
}
}
}
返回大小;
}

二进制序列化还是XML?XML将有一个/相当大的/差异,而如果你只是寻找一个一般性的估计,二进制可能或多或少是准确的。@Spencer-我认为这两者都不准确……为什么这是一个社区维基?这里的假设太多了。为什么不使用内存分析器呢?