Is there a way to programmatically and accurately determine the amount of memory used by an object in c#? I am not concerned with how slow the process is, so running GCs left and right is acceptable (of course I'd prefer something more efficient).
Serializing objects and looking at the resulting length doesn't seem very accurate (in a simple test of this method, I saw that an integer returned a value of 54).
Using GC.GetTotalMemory(true)
seems to produce inconsistent values, not to mention they appear too large.
Using Marshal.SizeOf(object)
produces accurate results, but only appears to work with primitives.
If nothing along those lines is available, an alternative would be to calculate sizes based on the structures used and the primitives involved. This would also be acceptable (though upsetting), but I'd need to know the correct method of calculating object overheads, etc. Any literature that would show me a way to do this would be awesome.
Similar SO questions (none of which seemed to have concrete methods for accurate calculation of object size):
How much memory does a C#/.NET object use?
How to get memory available or used in C#
How to get object size in memory?
sizeof() equivalent for reference types?
Tools to profile memory (non-programmatic approach):
http://www.microsoft.com/en-us/download/details.aspx?id=16273
Find out how much memory is being used by an object in C#?
JavaScript uses double-precision (64-bit) floating point numbers. 64 bits are 8 bytes, but each number actually takes up an average of 9.7 bytes. Likewise, Chrome shows the size of each individual empty array as 32 bytes and the size of each empty object as 56 bytes.
reference variables (refs to other objects) take 4 or 8 bytes (32/64 bit OS ?) int16, Int32, Int64 take 2,4, or 8 bytes, respectively...
jvisualvm is one of the memory analysis tools for Java used to analyze the runtime behavior of a Java application. It traces a running Java program, checking its memory and CPU consumption. Also, it is used to create a memory heap dump to analyze the objects in the heap.
another idea is to have a helper class to do this by reflecting the object and extract its all data members and gather all fields size by sizeof() , it will be a little bit complicated but it is implementable
this class will calculate the actual size of an object , but i have tested it just a few times and a few objects were tested but i think i will be working.
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With