A thread-safe cache for .NET applications that provides automatic indexing of the cached items.
using System;
using AutoIndexCache;
public class User
{
public Int64 GroupId { get; set; }
public Int64 Id { get; set; }
public Boolean IsActive { get; set; }
public String UserName { get; set; }
}
public class Program
{
public static void Main(String[] args)
{
var cache = new AutoIndexCache();
// Fill the cache with items:
cache.Items<User>().Fill(LoadUsers());
// Get all users:
cache.Items<User>().GetAllItems();
// Get the user that has the Id 1:
cache.Items<User>().UniqueIndex(a => a.Id).GetItemOrDefault(1);
// Get all users that belong to group 1:
cache.Items<User>().NonUniqueIndex(a => a.GroupId).GetItems(1);
// Get all active users of group 10:
cache.Items<User>().NonUniqueIndex(a => (a.IsActive, a.GroupId)).GetItems((true, 10));
// Get all Ids of users:
cache.Items<User>().UniqueIndex(a => a.Id).GetKeys();
}
private static User[] LoadUsers()
{
var result = new User[10_000];
for (var i = 1; i <= result.Length; i++)
{
result[i-1] = new() { Id = i, UserName = "User " + i, GroupId = i % 2 == 0 ? 2 : 1, IsActive = i % 2 == 0 };
}
return result;
}
}
AutoIndexCache is blazingly fast (as a cache should be).
However, some overhead is still needed to make it thread-safe and for the auto indexing, so a hand crafted custom solution might be even faster.
In the following benchmarks AutoIndexCache is compared to the Dictionary<TKey,TValue> type.
You can find the source code of the bechmarks here.
In these benchmarks the Dictionary<TKey,TValue> is used to index cached items.
There is hardly any faster soltuion in .NET to index cached items.
However, the Dictionary is completely non-thread-safe.
In these benchmarks the AutoIndexCache is used.
In these bechmarks, also, the AutoIndexCache is used.
However, a trick was applied to drastically improve the performance:
To access cached items you need to call the AutoIndexCache.Items method.
And to access indexes you need to call the ItemsList.NonUniqueIndex and ItemsList.UniqueIndex methods.
These methods have some overhead, because they need to be thread-safe.
Instead of calling these method each time you want to access cached items or indexes, you can just call them once and store their return values in fields (so in essence, you are caching the cache 😃).
This way the performance of the cache is improved drastically.
So instead of this:
class Service
{
private readonly AutoIndexCache cache;
public Service(AutoIndexCache cache)
{
this.cache = cache;
}
public User? GetUserById(Int64 id)
{
return this.cache.Items<User>().UniqueIndex(a => a.Id).GetItemOrDefault(id);
}
}
you do this:
class Service
{
private readonly AutoIndexCache cache;
private readonly IItemList<User> users;
private readonly IUniqueIndex<User, Int32> userById;
public Service(AutoIndexCache cache)
{
this.cache = cache;
this.users = this.cache.Items<User>();
this.userById = this.users.UniqueIndex(a => a.Id);
}
public User? GetUserById(Int64 id)
{
return this.userById.GetItemOrDefault(id);
}
}
This library is licensed under the MIT license.
First, install NuGet.
Then download a release from the releases page and install via the NuGet Package Manager:
PM> Install-Package AutoIndexCache -Source PathToTheNuGetPackage
The API documentation can be found here.
- David Liebeherr ([email protected])