System.Runtime.Caching内存缓存c#中每个对象占用的列表大小

Der*_*nch 5 c# caching

我正在使用ac#memory cache(System.Runtime.Caching)并且它正在填满,并使用比预期更多的ram.无论如何都要列出缓存中每个对象占用缓存的大小

我想编写与此类似的代码,以便我可以确定哪个特定项目导致了问题?

private void ListSizeOfEachItemInCache()
{
    foreach {var item in Cache.Items}
    {
        Console.WriteLine(string.Format(item.Key, item.CacheSize));
    }
}
Run Code Online (Sandbox Code Playgroud)

我的项通常是包含其中集合的类,并且具有大对象图.但是,如果我将它们序列化到磁盘,使用数据协定序列化程序,它们似乎不会填充磁盘上的空间,因为它们似乎在RAM中.这导致我认为文件缓存可能更好(因为从远程数据库中检索项目 - 甚至不在本地).

private static readonly MemoryCache Cache = MemoryCache.Default;
Run Code Online (Sandbox Code Playgroud)

我已经看到有关在内存中列出对象大小的其他问题,但这是不同的,因为我想要它在内存缓存中占用的确切大小(我不能假设它会完全相同,也许它有一些其他开销,因为缓存需要知道一些其他数据,例如何时添加,它的到期策略等).

Kel*_*ton 0

是的,你很可能无法得到确切的数字。您能做的最好的事情就是使用反射来迭代对象的层次结构并使用 来计算所有值类型的大小sizeof。但这仍然无法告诉您确切的尺寸。

对于我提到的那个例子,你可以使用这样的代码

void Main()
{
    var types = new List<object>{
        (byte)1,
        (short)1,
        (int)1,
        (long)1,
        (double)1,
        (decimal)1,
        (float)1,
        "omg afd obj amd",
        "omg afd obj amd omg afd obj amd omg afd obj amd omg afd obj amd omg afd obj amd omg afd obj amd omg afd obj amd ",
        new Exception("Holy Maceral"),
    };

    foreach(var o in types)
    {
        Console.WriteLine("Size of {0} == {1}",o.GetType().Name,o.SizeOf());
    }
}
public static class ExtensionMethods
{
    public static int SizeOf(this object obj)
    {
        int size = 0;
        if(obj == null)
            return 0;
        Type type = obj.GetType();

        if(type.IsValueType)
        {
            return type.SizeOfType();
        }

        PropertyInfo[] info = type.GetProperties();
        foreach(PropertyInfo property in info)
        {
            if(property.GetIndexParameters().Length > 0)
            {
                var ip = property.GetIndexParameters().First();
                //Console.WriteLine(info);
                var len = (int)info.FirstOrDefault(x=>x.Name == "Length" || x.Name == "Count").GetValue(obj);
                for(var i = 0;i<len;i++)
                {
                    size += property.GetValue(obj,new object[1]{i}).SizeOf();
                }
            }
            else if(property.GetGetMethod().ReturnType.IsArray)
            {
                var arr = property.GetGetMethod().Invoke(obj,null);
                foreach(var a in (Array)arr)
                {
                    size+= a.SizeOf();
                }
            }
            else if(property.PropertyType.IsValueType)
            {
                var val = property.GetValue(obj,null);
                unsafe
                {
                    size += property.PropertyType.SizeOfType();
                }
            }
            else{
                size += property.GetValue(obj,null).SizeOf();
            }
        }
        return size;
    }

    public static int SizeOfType(this Type type)
    {
        if(type.IsValueType == false)
            throw new ArgumentException("type must be value type");

        return Marshal.SizeOf(type);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出

Size of Byte == 1
Size of Int16 == 2
Size of Int32 == 4
Size of Int64 == 8
Size of Double == 8
Size of Decimal == 16
Size of Single == 4
Size of String == 19
Size of String == 116
Size of Exception == 36
Run Code Online (Sandbox Code Playgroud)

它不是 100% 完美,并且可能无法在不进行一些调整的情况下对每个对象都起作用,但它应该能够找出哪个对象是最令人反感的。