NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
NuGet · #1637 most downloaded on NuGet
High performance, thread-safe in-memory caching primitives for .NET.
Last release 1 months ago
27 Aug 2026
Release timing varies
gaps range from 2 weeks to 10 months
Some releases are documented
notes for 10 of 33 stable releases
Nothing withdrawn
no release was ever pulled
6 years old
33 releases · first in 2020
One column per quarter.
Fixed a ConcurrentLfu.Trim thread safety bug that could corrupt internal data structures when called concurrently with write operations.
ConcurrentLfu.Trim thread safety bug that could corrupt internal data structures when called concurrently with write operations.Full changelog: v2.6.0...v2.6.1
Added Alternate Lookup support across ICache , IAsyncCache , IScopedCache , and IAsyncScopedCache , enabling allocation free alternate key lookups via
ICache, IAsyncCache, IScopedCache, and IAsyncScopedCache, enabling allocation free alternate key lookups via ReadOnlySpan<char> on caches with a string primary key.ref struct support for the TArg generic type parameter in synchronous GetOrAdd methods, allowing stack-only arguments to be passed in.ConcurrentLfu, configured by calling builder WithEvents. ConcurrentLfu now has events enabled by default.ConcurrentLfu for a minor performance optimization.ScopedAtomicFactory, where scope initialization/disposal could observe stale state under contention.BackgroundThreadScheduler completion task to return completed when it is immediately disposed prior to executing any work.Full changelog: v2.5.4...v2.6.0
Eagerly purge deleted items from internal ConcurrentLru queues. Previously, deleted items remain in the internal queues until fully cycled out of cold
ConcurrentLru queues. Previously, deleted items remain in the internal queues until fully cycled out of cold. Instead, purge them as items transition from queue to queue (e.g. from hot to warm) as part of cycle.UnobservedTaskException for value creation when using AsAsyncCache()/AsyncAtomicFactory/ScopedAsyncAtomicFactory. If there is an exception when invoking the value factory delegate, the internal TaskCompletionSource has an exception set that previously was not observed unless another thread concurrently evaluated the result. Fixed by @advdotnet.ConcurrentLru.Trim() avoid incorrectly trimming an extra warm item when values are trimmed from cold but not warm.ConcurrentLru.TrimExpired() is now thread safe.Full changelog: v2.5.3...v2.5.4
Eliminate volatile writes in ConcurrentLru internal bookkeeping code for pure reads, improving concurrent read throughput by 175%.
ConcurrentLru internal bookkeeping code for pure reads, improving concurrent read throughput by 175%.CmSketch using Neon intrinsics for ARM CPUs. This results in slightly better ConcurrentLfu cache throughput measured on Apple M series and Azure Cobalt 100 CPUs.CmSketch. This results in slightly better ConcurrentLfu throughput on CPUs without vector support (i.e. neither x86 AVX2 nor Arm Neon).CmSketch allocates the internal buffer using the pinned object heap on .NET6 or newer. Use of the fixed statement is removed, eliminating a very small overhead. Sketch block pointers are then aligned to 64 bytes, guaranteeing each block is always on the same CPU cache line. This provides a small speedup for the ConcurrentLfu maintenance thread by reducing CPU cache misses.MethodImpl(MethodImplOptions.AggressiveInlining) and removal of local variables to improve performance on .NET8/9 and dynamic PGO.Full changelog: v2.5.2...v2.5.3
Fix race between update and TryRemove(KeyValuePair) for both ConcurrentLru and Fix ConcurrentLfu . Prior to this fix, values may be deleted if the val
TryRemove(KeyValuePair) for both ConcurrentLru and Fix ConcurrentLfu. Prior to this fix, values may be deleted if the value is updated to no longer match the TryRemove input argument while TryRemove is executing.ConcurrentLfu torn writes for large structs using SeqLock.Full changelog: v2.5.1...v2.5.2
Fix ConcurrentLfu time-based expiry policy failing to update the entry's expiry on read. Prior to this fix, expiry is only updated when the read buffe
ConcurrentLfu time-based expiry policy failing to update the entry's expiry on read. Prior to this fix, expiry is only updated when the read buffer is processed (following a cache write, or when the read buffer is full).ConcurrentLru torn writes for large structs using SeqLock.ConcurrentLru AfterAccessPolicy and DiscretePolicy.TickCount64 to evaluate current time for .NET Standard on Windows, Duration.SinceEpoch is 5x faster resulting in lower latency lookups for ConcurrentTLru/ConcurrentTLfu.Stopwatch.GetTimestamp to evaluate current time on MacOS, Duration.SinceEpoch is about 20% faster resulting in slightly lower latency lookups for ConcurrentTLru/ConcurrentTLfu.Full changelog: v2.5.0...v2.5.1
These new methods are excluded in the base interfaces for .NET Standard, since adding them would be a breaking change .
ConcurrentLfu, matching ConcurrentLru. This closely follows the implementation in Java's Caffeine, using a port of Caffeine's hierarchical timer wheel to perform all operations in O(1) time. Expire after write, expire after access and expire after using IExpiryCalculator can be configured via ConcurrentLfuBuilder extension methods.ICacheExt and IAsyncCacheExt to enable client code compiled against .NET Standard to use the builder APIs and cache methods added since v2.0. These new methods are excluded in the base interfaces for .NET Standard, since adding them would be a breaking change.Duration convenience methods FromHours and FromDays.Full changelog: v2.4.1...v2.5.0
Fixed a race condition in ConcurrentLfu for add-remove-add of the same key.
ConcurrentLfu for add-remove-add of the same key.MpscBoundedBuffer.Clear() is now thread safe, fixing a race in ConcurrentLfu clear.ConcurrentLru Count and IEnumerable<KeyValuePair<K,V>> to filter out expired items when used with time-based expiry.<nullable>enable</nullable>, and APIs are annotated to support null reference type static analysis.Full changelog: v2.4.0...v2.4.1
Provide two new time-based expiry schemes for ConcurrentLru :
ConcurrentLru:
IExpiryCalculator. Expiry time may be set independently at creation, after a read and after a write.TryRemove overloads with ConcurrentDictionary for IAsyncCache and AsyncAtomicFactory, matching the implementation for ICache added in v2.3.0. This adds two new overloads:
bool TryRemove(K key, out V value) - enables getting the value that was removed.bool TryRemove(KeyValuePair<K, V> item) - enables removing an item only when the key and value are the same.AsyncAtomicFactory with a plain ConcurrentDictionary. This is similar to storing an AsyncLazy<T> instead of T, but with the same exception propagation semantics and API as ConcurrentDictionary.GetOrAdd.AtomicFactory value initialization logic modified to mitigate lock convoys, based on the approach given here.ConcurrentLru.Clear to correctly handle removed items present in the internal bookkeeping data structures.Full changelog: v2.3.3...v2.4.0
Eliminated all races in ConcurrentLru eviction logic, and the transition between the cold cache and warm cache eviction routines. This prevents a vari
ConcurrentLru eviction logic, and the transition between the cold cache and warm cache eviction routines. This prevents a variety of rare 'off by one item count' situations that could needlessly evict items when the cache is within bounds.ConcurrentLru.Clear() to always clear the cache when items in the warm queue are marked as accessed.ConcurrentLfu drain buffers logic to give ~5% better throughput (measured by the eviction throughput test).ConcurrentLfu drain buffers delegate to prevent allocating a closure when scheduling maintenance.BackgroundThreadScheduler and ThreadPoolScheduler now use TaskScheduler.Default, instead of implicitly using TaskScheduler.Current (fixes CA2008).ScopedAsyncCache now internally calls ConfigureAwait(false) when awaiting tasks (fixes CA2007).ConcurrentLru debugger display on .NET Standard.Full changelog: v2.3.2...v2.3.3
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →