ModernCaching 0.0.1
See the version list below for details.
dotnet add package ModernCaching --version 0.0.1
NuGet\Install-Package ModernCaching -Version 0.0.1
<PackageReference Include="ModernCaching" Version="0.0.1" />
paket add ModernCaching --version 0.0.1
#r "nuget: ModernCaching, 0.0.1"
// Install ModernCaching as a Cake Addin #addin nuget:?package=ModernCaching&version=0.0.1 // Install ModernCaching as a Cake Tool #tool nuget:?package=ModernCaching&version=0.0.1
ModernCaching
A 2-layer, performant and resilient caching solution for modern .NET.
A typical cache provided by this library consists of:
- a synchronous local cache that implements
ICache
- an asynchronous distributed cache that implements
IAsyncCache
(e.g. memcache, redis) - a data source that implements
IDataSource
(e.g. relational database, Web API, CPU intensive task...)
These 3 components form an IReadOnlyCache
.
The 2 cache layers are populated from the
IDataSource
with a backfilling mechanism when getting a value or by preloading some data
when building the cache.
ModernCaching doesn't provide implementations of
IAsyncCache
or IDataSource
because they are usually tied to the business. Only a single implementation of
ICache
is built-in:
MemoryCache
.
Installation
ModernCaching is available on Nuget.
dotnet add package ModernCaching
Features
- Strict API.
IReadOnlyCache
has only two methods:TryPeek
, a synchronous operation to only get the value if it's present in the local cache.TryGetAsync
, an asynchronous operation to get the first fresh value in the local cache, distributed cache or the data source, in that order.
- Performance. Unlike other caching libraries that use a
string
as a key or anobject
as value or both,ModernCaching
uses a generic key and value. That way, getting a value from the local cache doesn't require any allocation for simple type keys such asint
or more complex user-defined objects. See the benchmarks. - Resilience. With its fixed number of layers, each behavior is clearly defined when one of these layers is down. For instance, the data source is skipped if the distributed cache is unavailable to avoid DDOSing it.
- Instrumentation. Metrics are exposed using OpenTelemetry API. Errors from user-code are logged if a logger is specified.
Example
This example caches the user information. The first layer is implemented with an
in-memory cache, the second one is a redis where we specify how to create the
key and how to serialize the value using the interface IKeyValueSerializer
.
Behind these two layers stands the IDataSource
.
var cache = await new ReadOnlyCacheBuilder<Guid, User>("user-cache", new UserDataSource("Host=localhost;User ID=postgres"))
.WithLocalCache(new MemoryCache<Guid, User>())
.WithDistributedCache(new RedisAsyncCache(redis), new ProtobufKeyValueSerializer<Guid, User>())
.BuildAsync();
Guid userId = new("cb22ff11-4683-4ec3-b212-7f1d0ab378cc");
bool found = cache.TryPeek(userId, out User? user); // Only check local cache with background reload.
(bool found, User? user) = await cache.TryGetAsync(userId); // Check all layers for a fresh value.
The rest of the code as well as other examples can be found in src/ModernCaching.ITest.
Benchmarks
Benchmark of the very hot path of different caching libraries (CacheTower, FusionCache, EasyCaching), that is, getting locally cached data. The .NET ConcurrentDictionary was also added as a baseline.
Method | Mean | Error | StdDev | Ratio | RatioSD | Allocated |
---|---|---|---|---|---|---|
ConcurrentDictionary | 9.192 ns | 0.0760 ns | 0.0710 ns | 1.00 | 0.00 | - |
ModernCaching | 22.749 ns | 0.1254 ns | 0.1173 ns | 2.47 | 0.02 | - |
CacheTower | 117.624 ns | 0.4935 ns | 0.4375 ns | 12.80 | 0.11 | 96 B |
FusionCache | 336.466 ns | 1.0357 ns | 0.9181 ns | 36.61 | 0.34 | 184 B |
EasyCaching | 346.405 ns | 1.0457 ns | 0.9781 ns | 37.69 | 0.30 | 264 B |
This library has similar performance as a raw ConcurrentDictionary since its hot path is a thin layer around it. It doesn't allocate anything, putting no pressure on the garbage collector.
Code can be found in src/ModernCaching.Benchmarks.
Instrumentation
Metrics
Metrics are exposed using .NET implementation of the OpenTelemetry Metrics API
(System.Diagnostics.Metrics)
under the source name ModernCaching
. They can be exported using the
OpenTelemetry .NET SDK.
Logs
Use WithLoggerFactory
on the builder to log all user-code errors coming from
IAsyncCache
,
IKeyValueSerializer
or
IDataSource
.
License
All code found in this repository is licensed under MIT. See the LICENSE file in the project root for the full license text.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
.NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.1 is compatible. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Microsoft.Extensions.Logging.Abstractions (>= 3.0.0)
- Microsoft.Extensions.ObjectPool (>= 3.0.0)
- System.Diagnostics.DiagnosticSource (>= 6.0.0-preview.7.21377.19)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.