10

プログラムで正確に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#のオブジェクトによって使用されているメモリの量を調べますか?

4

2 に答える 2

3

もう 1 つのアイデアは、オブジェクトをリフレクトし、そのすべてのデータ メンバーを抽出し、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;
        }
    }
}
于 2012-09-24T05:21:32.793 に答える
0
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);

役に立つかどうかはわかりませんが、このリンクを参照してみてください...特に図4

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

于 2012-09-24T04:53:02.613 に答える