Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to measure current size of .NET Memory Cache 4.0?

Tags:

c#

.net

Currently we're using the .NET Memory Cache 4.0 for the Caching requirements. (not ASP.NET Cache, not any external Cache)

Looking at the '.NET Memory Cache 4.0' performance counters, there is data around Cache Hits, Misses, Entries, Trims etc. but nothing related to Size.

Is there is a way of measuring/knowing the current size of the Cache used by the Production Application?

I want to be able to capture this data at various points in time and get the average size of the cache.

like image 396
Raja Nadar Avatar asked Mar 13 '14 22:03

Raja Nadar


People also ask

What is in memory cache in .NET core?

In-Memory Caching in ASP.NET Core is the simplest form of cache in which the application stores data in the memory of the webserver. This is based on the IMemoryCache interface which represents a cache object stored in the application's memory.

What is the default size of cache?

The default data cache size is an absolute value, and the minimum size for the cache size is 256 times the logical page size; for 2KB, the minimum is 512KB: for 16KB, the minimum is 4MB. The default value is 8MB.

What is the maximum size of cache memory?

The maximum theoretical cache size is 2 GB. The size of cache you can specify is limited by the amount of physical memory and paging space available to the system. The shared class cache consists of memory mapped files that are created on disk and remain when the operating system is restarted.


1 Answers

It is an ugly implementation detail that Microsoft did not want to expose at all. Measuring object sizes in .NET is not in general possible. MemoryCache uses a fairly nasty backdoor to implement its memory limit trigger, it uses the DACCESS component of the CLR, actually intended to help implement memory profilers.

You can see it with the debugger so it isn't like you can't get to it. You just have to write very ugly code to dig through the private fields:

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);     } } 

Seemed to work pretty well on .NET 4.6.1, not extensively tested. This is okay to get the lay of the land, just don't depend on it since it may break with any .NET update.

like image 76
Hans Passant Avatar answered Oct 09 '22 03:10

Hans Passant