我知道这篇文章可能看似重复,但我阅读了所有这些文章并开发了一个测试主题的样本
Find size of object instance in bytes in c# http://www.codeproject.com/Questions/177604/Size-of-a-class-in-c How to get object size in memory? Getting the size of a field in bytes with C# http://blogs.msdn.com/b/cbrumme/archive/2003/04/15/51326.aspx
我有一个类whiteout任何属性或字段,它只是为了测试它的大小是空的。
[Serializable]
public class MemberStateModel
{
}
我创建一个对象并通过以下代码获取它的大小:
static void Main(string[] args)
{
MemberStateModel o = new MemberStateModel() {};
long size;
using (Stream s = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(s, o);
size = s.Length;
}
}
现在它的大小显示数字159,通过那些帖子我认为这意味着我的o大小是159kbyte但是 我认为它不正确的方式和空物体不能有这个尺寸,是真的吗?
这对我来说非常重要,因为我将一些用户的数据存储在会话中,如果这个大小在我的网站中添加用户增长,我将需要更多的物理内存来处理我的Web应用程序
答案 0 :(得分:1)
BinaryFormatter告诉您将类序列化为二进制所需的字节数。这与类在内存中占用的大小非常不同。例如,BinaryFormatter将有关类型的信息写入流中。
对象在内存中使用的大小不是在编译时定义的,而是在运行时定义的,因为JIT编译器决定最终的布局。现在问题是如何找出尺寸。虽然我有一个结构的解决方案(创建一个数组,做指针算术),我不知道如何找到类的。一种解决方案是将您的类MemberStateModel
定义为结构,测量它,然后转回一个类,假设它将具有相同的大小。
您还可以通过将字段的大小计算为下限来估计大小(因为填充发生)。如果您的类具有对其他类实例的引用,则几乎无法估计它。
答案 1 :(得分:1)
在将其放入本地内存缓存之前,我需要了解对象的内存消耗,因此我编写了一个扩展方法,该方法迭代对象的公共属性并总结大小值。如果它是IEnumerable或Array,它将遍历项目并计算其大小。这不是最好的方法,但是对我来说足够好,因为对我的缓存没有比这更复杂的要求了。
public static class ObjectMemorySizeCalculator
{
static int OBJECT_SIZE = IntPtr.Size == 8 ? 24 : 12;
static int POINTER_SIZE = IntPtr.Size;
public static long GetMemorySize(this object obj)
{
long memorySize = 0;
Type objType = obj.GetType();
if (objType.IsValueType)
{
memorySize = Marshal.SizeOf(obj);
}
else if (objType.Equals(typeof(string)))
{
var str = (string)obj;
memorySize = str.Length * 2 + 6 + OBJECT_SIZE;
}
else if (objType.IsArray)
{
var arr = (Array)obj;
var elementType = objType.GetElementType();
if (elementType.IsValueType)
{
long elementSize = Marshal.SizeOf(elementType);
long elementCount = arr.LongLength;
memorySize += elementSize * elementCount;
}
else
{
foreach (var element in arr)
{
memorySize += element != null ? element.GetMemorySize() + POINTER_SIZE : POINTER_SIZE;
}
}
memorySize += OBJECT_SIZE;
}
else if (obj is IEnumerable)
{
var enumerable = (IEnumerable)obj;
foreach(var item in enumerable)
{
var itemType = item.GetType();
memorySize += item != null ? item.GetMemorySize() : 0;
if (itemType.IsClass)
memorySize += POINTER_SIZE;
}
memorySize += OBJECT_SIZE;
}
else if (objType.IsClass)
{
var properties = objType.GetProperties();
foreach (var property in properties)
{
var valueObject = property.GetValue(obj);
memorySize += valueObject != null ? valueObject.GetMemorySize() : 0;
if (property.GetType().IsClass)
memorySize += POINTER_SIZE;
}
memorySize += OBJECT_SIZE;
}
return memorySize;
}
答案 2 :(得分:0)
首先,它不是159千字节,而是159字节。甚至空对象占用空间的原因是因为BinaryFormatter也存储了一些元数据。本文提供了一些解释:http://www.codeproject.com/Articles/311944/BinaryFormatter-or-Manual-serializing。
要估算解决方案的内存复杂性,可以使用内存分析器。例如,我使用了这个,甚至试用版也很有用:http://www.jetbrains.com/profiler/。