Daily Knowledge Drop
Coming with .NET 7, the MemoryCacheStatistics
class, accessed through IMemoryCache.GetCurrentStatistics
can provider useful statistics regarding the state of the memory cache. These include:
- how many items are currently in the cache
- the current estimate size of the cache
- the number of times the cache has been queried for a value, and the value was not present (misses)
- the number of times the cache has been queried for a value, and the value was present (hits)
These stats can be leveraged to better understand how/if the cache mechanism is correctly configured and being used optimally.
Cache configuration
The first step is to register the require cache implementation instances with the dependency injection container. This is done using the AddMemoryCache extension method:
builder.Services
.AddMemoryCache(memCacheOptions =>
{
memCacheOptions.TrackStatistics = true;
memCacheOptions.SizeLimit = 1024;
});
- For stats to be tracked, the
MemoryCacheOptions.TrackStatistics
value (memCacheOptions.TrackStatistics in the above example) needs to be set totrue
- For the
EstimateSize
property of the statistics to be tracked, the cache needs to have a SizeLimit specified. The SizeLimit does not represent memory size, but number of units - in the above example, the limit has been set to 1024 units, and when items are added to the cache one byte will be treated as a unit (this is not a required, its up to the developer to decide how many "units" each item added to the cache is worth)
Cache usage
Set values
Now that the cache is configured, the next step is to start using it to store values. A simple getnumber
endpoint is defined, which will return the number passed in:
- if the number does not exist in the cache, it will be added to the cache and returned
- if the number already exists in the cache, it will be returned from the cache
// get the number from the route
// get the IMemoryCache from the DI container
app.MapGet("/getnumber/{number}", ([FromRoute]int number,
[FromServices] IMemoryCache cache) =>
{
// first check the cache to see if the number
// exists there
if(cache.TryGetValue(number, out var value))
{
return $"'{value}' retrieved from cache";
}
// if it didn't exist, add it to the cache
cache.Set(number, number, new MemoryCacheEntryOptions { Size = sizeof(int)});
// return
return $"'{number}' added to cache";
});
Invoking the endpoint with a number for the first time /getnumber/1
, will result in:
'1' added to cache
While invoking subsequent times with the same number will result in:
'1' retrieved from cache
The cache has been configured and the endpoint called a number of times, with unique and duplicate numbers, so next let's have a look at the stats.
Get statistics
To get a snapshot of the IMemoryCache statistics, the GetCurrentStatistics
method is used:
app.MapGet("/getstats", ([FromServices] IMemoryCache cache) =>
{
return cache.GetCurrentStatistics();
});
A sample return snapshot:
{
"currentEntryCount":6,
"currentEstimatedSize":24,
"totalMisses":6,
"totalHits":2
}
In this example:
6 items have been added
to the cache- the 6 items take up
24 of the available 1024 units
available (6 x 4 bytes) - the cache has been checked and did
not contain the queried value 6 times
- the cache has been checked and
did contain the queried value twice
Notes
This information is very valuable and can be leveraged to confirm if the cache configured for an application is successfully being used - over time, one would want to see a high number of hits and relatively low number of misses. This information can be used to determine if the cache strategy needs to be modified (cache based on a different key) or maybe increase or decrease the cache size.
References
IMemoryCache.GetCurrentStatistics Method
Daily Drop 183: 17-10-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.