programmatically find memory used by object

后端 未结 2 1146
一向
一向 2021-02-08 22:38

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 a

相关标签:
2条回答
  • 2021-02-08 22:46

    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;
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-08 23:07
    object obj = new List<int>(); // whatever you want to get the size of
    RuntimeTypeHandle th = obj.GetType().TypeHandle;
    int size = *(*(int**)&th + 1);
    Console.WriteLine(size);
    

    I dont know whether it is useful to you or not...but try to refer this link...espacialy fig.4

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

    0 讨论(0)
提交回复
热议问题