目前我们正在使用.NET Memory Cache 4.0来满足缓存要求.(不是ASP.NET缓存,不是任何外部缓存)
查看".NET内存缓存4.0"性能计数器,有关于缓存命中,未命中,条目,修剪等的数据,但与大小无关.
是否有一种方法可以测量/了解生产应用程序使用的高速缓存的当前大小?
我希望能够在不同的时间点捕获这些数据并获得缓存的平均大小.
Han*_*ant 23
这是一个丑陋的实现细节,微软根本不想公开.在.NET中测量对象大小通常是不可能的.MemoryCache使用一个相当讨厌的后门来实现其内存限制触发器,它使用CLR的DACCESS组件,实际上旨在帮助实现内存分析器.
你可以用调试器看到它,所以它不像你无法达到它.你只需编写非常难看的代码来挖掘私有领域:
using System;
using System.Reflection;
using System.Runtime.Caching;
public static class MemoryCacheHackExtensions {
public static long GetApproximateSize(this MemoryCache cache) {
var statsField = typeof(MemoryCache).GetField("_stats", BindingFlags.NonPublic | BindingFlags.Instance);
var statsValue = statsField.GetValue(cache);
var monitorField = statsValue.GetType().GetField("_cacheMemoryMonitor", BindingFlags.NonPublic | BindingFlags.Instance);
var monitorValue = monitorField.GetValue(statsValue);
var sizeField = monitorValue.GetType().GetField("_sizedRef", BindingFlags.NonPublic | BindingFlags.Instance);
var sizeValue = sizeField.GetValue(monitorValue);
var approxProp = sizeValue.GetType().GetProperty("ApproximateSize", BindingFlags.NonPublic | BindingFlags.Instance);
return (long)approxProp.GetValue(sizeValue, null);
}
}
Run Code Online (Sandbox Code Playgroud)
似乎在.NET 4.6.1上工作得很好,没有经过广泛测试.这是可以获得的土地,只是不依赖它,因为它可能打破任何.NET更新.
我使用了原始代码并且必须进行微调,我使用"_sizedRefMultiple"而不是"_sizedRef"来使其与.NET 4.6一起使用.
public static class MemoryCacheHackExtensions
{
public static long GetApproximateSize(this MemoryCache cache)
{
var statsField = typeof(MemoryCache).GetField("_stats", BindingFlags.NonPublic | BindingFlags.Instance);
var statsValue = statsField.GetValue(cache);
var monitorField = statsValue.GetType().GetField("_cacheMemoryMonitor", BindingFlags.NonPublic | BindingFlags.Instance);
var monitorValue = monitorField.GetValue(statsValue);
var sizeField = monitorValue.GetType().GetField("_sizedRefMultiple", BindingFlags.NonPublic | BindingFlags.Instance);
var sizeValue = sizeField.GetValue(monitorValue);
var approxProp = sizeValue.GetType().GetProperty("ApproximateSize", BindingFlags.NonPublic | BindingFlags.Instance);
return (long)approxProp.GetValue(sizeValue, null);
}
}
Run Code Online (Sandbox Code Playgroud)