Memory cache
The Memory kind stores the values in the memory of the current process. Use it for data that is cheap to rebuild and
that does not need to be shared between instances of a service, and as the default cache on a developer machine.
It is one of the providers of the caching guide; read that page first for the Caching section and the
named cache concept.
What it solves
MemoryCache (MemoryCache) wraps the MemoryDistributedCache of
Microsoft.Extensions.Caching.Memory. Like the other providers, it serializes the values, so a cached object is a copy:
changing the object after Put does not change what Get returns, and the size limit counts serialized bytes.
Packages involved
| Package | Use it for |
|---|---|
Arc4u.Caching.Memory |
The MemoryCache class and AddMemoryCacheKind(). |
Arc4u.Caching |
ICacheContext, AddCacheContext, and AddMemoryCache with MemoryCacheOption (namespace Arc4u.Configuration.Memory). |
Arc4u.Serializer.JSon |
The serializer (any IObjectSerialization works). |
Install
dotnet add package Arc4u.Caching.Memory --prerelease
dotnet add package Arc4u.Serializer.JSon --prerelease
Arc4u.Caching.Memory brings Arc4u.Caching.
Configuration
appsettings.json
{
"Caching": {
"Default": "Volatile",
"Caches": [
{
"Name": "Volatile",
"Kind": "Memory",
"IsAutoStart": true,
"Settings": {
"SizeLimitInMB": 50,
"CompactionPercentage": 0.2
}
}
]
}
}
The settings bind to MemoryCacheOption:
| Key | Type | Default | Description |
|---|---|---|---|
Caching:Caches:n:Settings:SizeLimitInMB |
long |
100 |
Maximum size of the cache, in megabytes, of serialized data. |
Caching:Caches:n:Settings:CompactionPercentage |
double |
0.2 |
Fraction of the entries removed when the limit is reached. |
Caching:Caches:n:Settings:SerializerName |
string |
none | Key of the IObjectSerialization to use. When empty or not registered, the unkeyed IObjectSerialization is used. |
Note
MemoryCacheOption.SizeLimitInMB keeps the value in megabytes, as configured. The limit given to the underlying
cache is MemoryCacheOption.SizeLimitInBytes (SizeLimitInMB times 1,048,576). A Memory cache declared without
a Settings section uses the default of 100 MB.
Code
// Program.cs
using Arc4u.Caching;
using Arc4u.Caching.Memory;
using Arc4u.Dependency;
using Arc4u.Serializer;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddILogger();
builder.Services.AddCacheContext(builder.Configuration);
builder.Services.AddSingleton<IObjectSerialization, JsonSerialization>();
builder.Services.AddMemoryCacheKind();
var app = builder.Build();
var cache = app.Services.GetRequiredService<ICacheContext>().Default;
cache.Put("greeting", "hello");
Console.WriteLine(cache.Get<string>("greeting"));
Common scenarios
Declare several memory caches
Each name has its own store and limit. Give a small, short-lived cache its own name instead of sharing one limit:
{
"Caching": {
"Default": "Volatile",
"Caches": [
{ "Name": "Volatile", "Kind": "Memory", "IsAutoStart": true, "Settings": { "SizeLimitInMB": 100 } },
{ "Name": "Lookups", "Kind": "Memory", "IsAutoStart": true, "Settings": { "SizeLimitInMB": 10, "SerializerName": "gzip" } }
]
}
}
"SerializerName": "gzip" needs a keyed serializer registered with that key; see Serialization.
Expire and evict
Put with a TimeSpan expires the value (absolute, or sliding with isSlided: true). When the size limit is reached,
the cache removes CompactionPercentage of its entries in the background, and the Put that hits the limit throws
DataCacheException (the value is not stored, and the previous value of the key is removed). Values are never shared with another process: after a restart, or
in a second instance of the service, the cache is empty.
Extensibility points
AddMemoryCacheKind() registers MemoryCache under the key Memory with TryAddKeyedTransient. Register your own ICache
under that key before calling it (or instead of it) to replace it, or under
another key for a new kind (see Caching).
Troubleshooting
Get returns null right after Put
Check that the timeout passed to Put is not already over. A value that does not fit in SizeLimitInMB is not
silently dropped: Put throws DataCacheException with a message about the size limit.
CacheNotInitializedException mentioning IObjectSerialization
No serializer could be resolved. Register builder.Services.AddSingleton<IObjectSerialization, JsonSerialization>().
See also
- Caching
- Serialization
- Arc4u.Caching.Memory in the API reference