Reputation: 5645
i know this article may seems duplicate but i read all of this articles and develop a sample to test theme
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
i have a class whiteout any properties or field, it is empty just to test size of it.
[Serializable]
public class MemberStateModel
{
}
i create a object and get size of it by bellow codes:
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;
}
}
now in size it shows number 159, by that posts i think it means my o size is 159kbyte but i think its not correct way and an empty object can not has this size, is it true?
it's very important for me because i store some user's data in session and if this size grows up by Added users in my site, i will need more physically memory to handle my web application
Upvotes: 1
Views: 12383
Reputation: 1288
I needed to know memory consumption of an object before putting it to Local In-Memory-Cache so I have written an extension method which iterates through the public properties of an the object and sums up the size values. If it's a IEnumerable or an Array it will iterate through items and calculate their size as well. This is not the best way but works good enough for me since I don't have more complicated requirements than this for my cache.
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;
}
Upvotes: 3
Reputation: 11132
The BinaryFormatter tells you how many bytes it needs to serialize the class to binary. This is very different from the size a class takes in memory. For instance, the BinaryFormatter writes information about the type into the stream.
The size that an object uses in memory is not defined at compile time but at runtime, since the JIT compiler decides on the final layout. Now comes the question how to find out the size. While I have a solution for structs (create an array, do pointer arithmetic), I am not sure how to find that out for classes. One solution would be to define your class MemberStateModel
as a struct, measure it, then turn back to a class, assuming it will have the same size.
You can also estimate the size, by counting the size of the fields as a lower bound (since padding occurs). If your class has references to other class instances, then it gets nearly impossible to estimate.
Upvotes: 1
Reputation: 35911
First of all, it's not 159 kbyte, but 159 bytes. The reason that even an empty object takes space is because BinaryFormatter stores also some meta-data with it. This article provides some explanation: http://www.codeproject.com/Articles/311944/BinaryFormatter-or-Manual-serializing.
To estimate the memory complexity of your solution you could use a memory profiler. For example, I used this one, and even a trial version is useful: http://www.jetbrains.com/profiler/.
Upvotes: 0