以编程方式查找对象使用的内存

有没有办法以编程方式准确地确定c#中对象使用的内存量? 我不关心这个过程有多慢,所以左右运行GC是可以接受的(当然我更喜欢更高效的东西)。

  • 序列化对象并查看结果长度似乎不太准确(在这个方法的简单测试中,我看到一个整数返回值为54)。

  • 使用GC.GetTotalMemory(true)似乎会产生不一致的值,更不用说它们看起来太大了。

  • 使用Marshal.SizeOf(object)生成准确的结果,但只能使用基元。

如果这些行中没有任何内容可用,则可以选择根据所使用的结构和所涉及的原语来计算大小。 这也是可以接受的(尽管令人不安),但我需要知道计算对象开销等的正确方法。任何能够向我展示这种方法的文献都会很棒。

类似的SO问题(其中没有一个似乎具有准确计算对象大小的具体方法):

C#/ .NET对象使用多少内存?

如何在C#中获取或使用内存

如何在内存中获取对象大小?

sizeof()等效于引用类型?

配置内存的工具(非程序化方法):

http://www.microsoft.com/en-us/download/details.aspx?id=16273

找出C#中对象使用了多少内存?

另一个想法是通过reflection对象并提取其所有数据成员并通过sizeof()收集所有字段大小来实现此操作,它会有点复杂但它是可实现的

这个类将计算一个对象的实际大小,但我已经测试了几次,并测试了一些对象,但我想我会工作。

 public class SizeHelper { private static int GetTypeSizeArray(string typeName, object objValue) { switch (typeName) { case "System.Double[]": return sizeof(System.Double) * ((System.Double[]) objValue).Length ; case "System.Single[]": return sizeof(System.Single) * ((System.Single[])objValue).Length; case "System.Char[]": return sizeof(System.Char) * ((System.Char[])objValue).Length; case "System.Int16[]": return sizeof(System.Int16) * ((System.Int16[])objValue).Length; case "System.Int32[]": return sizeof(System.Int32) * ((System.Int32[])objValue).Length; case "System.Int64[]": return sizeof(System.Int64) * ((System.Int64[])objValue).Length; case "System.UInt16[]": return sizeof(System.UInt16) * ((System.UInt16[])objValue).Length; case "System.UInt32[]": return sizeof(System.UInt32) * ((System.UInt32[])objValue).Length; case "System.UInt64[]": return sizeof(System.UInt64) * ((System.UInt64[])objValue).Length; case "System.Decimal[]": return sizeof(System.Decimal) * ((System.Decimal[])objValue).Length; case "System.Byte[]": return sizeof(System.Byte) * ((System.Byte[])objValue).Length; case "System.SByte[]": return sizeof(System.SByte) * ((System.SByte[])objValue).Length; case "System.Boolean": return sizeof (System.Boolean)*((System.Boolean[]) objValue).Length; default: return 0; } } public static int GetSize(object obj) { Type t = obj.GetType(); FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); int size = 0; foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType.BaseType.FullName.Equals("System.ValueType")) { size += GetTypeSize(fieldInfo.FieldType.FullName); } else if (fieldInfo.FieldType.BaseType.FullName.Equals("System.Array")) { var subObj = fieldInfo.GetValue(obj); if (subObj != null) size += GetTypeSizeArray(fieldInfo.FieldType.FullName, subObj); } else if(fieldInfo.FieldType.FullName.Equals("System.String")) { var subObj = fieldInfo.GetValue(obj); if (subObj != null) { size += subObj.ToString().Length*sizeof (System.Char); } } else { var subObj = fieldInfo.GetValue(obj); if (subObj != null) size += GetSize(subObj); } } return size; } private static int GetTypeSize(string typeName) { switch (typeName) { case "System.Double": return sizeof(System.Double); case "System.Single": return sizeof(System.Single); case "System.Char": return sizeof(System.Char); case "System.Int16": return sizeof(System.Int16); case "System.Int32": return sizeof(System.Int32); case "System.Int64": return sizeof(System.Int64); case "System.UInt16": return sizeof(System.UInt16); case "System.UInt32": return sizeof(System.UInt32); case "System.UInt64": return sizeof(System.UInt64); case "System.Decimal": return sizeof(System.Decimal); case "System.Byte": return sizeof(System.Byte); case "System.SByte": return sizeof(System.SByte); case "System.Boolean": return sizeof (System.Boolean); default: return 0; } } } 
 object obj = new List(); // whatever you want to get the size of RuntimeTypeHandle th = obj.GetType().TypeHandle; int size = *(*(int**)&th + 1); Console.WriteLine(size); 

我不知道它对你是否有用……但试着参考这个链接… espacialy fig.4

http://msdn.microsoft.com/en-us/magazine/cc163791.aspx#S9