Simple C# MemoryCache implementation – Understand the SizeLimit property

The .NET Core IMemoryCache is probably the simplest cache there is, and it is very easy to use, once you get your head around the weird SizeLimit property.

Especially when using the nice extension methods in this NuGet package:

But let’s code first, then discuss the SizeLimit.

SIMPLE MEMORY CACHE REPOSITORY:

using Microsoft.Extensions.Caching.Memory;
using System;

namespace MyCode
{
  public interface IMemoryCacheRepository
  {
    bool TryGetValue<T>(string key, out T value);
    void SetValue<T>(string key, T value);
    void Remove(string key);
  }
  
  public class MemoryCacheRepository : IMemoryCacheRepository
  {
    // We will hold 1024 cache entries
    private static readonly int _SIZELIMIT = 1024;
    // A cache entry expire after 15 minutes
    private static readonly int _ABSOLUTEEXPIRATION = 90;
     
    private MemoryCache Cache { get; set; }
     
    public MemoryCacheRepository()
    {
      Cache = new MemoryCache(new MemoryCacheOptions
      {
        SizeLimit = _SIZELIMIT
      });
    }
 
    // Try getting a value from the cache.
    public bool TryGetValue<T>(string key, out T value)
    {
      value = default(T);
 
      if (Cache.TryGetValue(key, out T result))
      {
        value = result;
        return true;
      }
 
      return false;
    }
 
    // Adding a value to the cache. All entries
    // have size = 1 and will expire after 15 minutes
    public void SetValue<T>(string key, T value)
    {
      Cache.Set(key, value, new MemoryCacheEntryOptions()
        .SetSize(1)
        .SetAbsoluteExpiration(TimeSpan.FromSeconds(_ABSOLUTEEXPIRATION))
      );
    }
 
    // Remove entry from cache
    public void Remove(string key)
    {
      Cache.Remove(key);
    }
  }
}

Usage:

MemoryCacheRepository cache = new MemoryCacheRepository();

// This is pseudocode. The cache can get any
// type of object. You should define the object to
// get.
string cacheKey = "somekey";
string objectToCache = new ArbitraryObject();

// Getting the object from cache:
if (cache.TryGetValue(cacheKey, out ArbitraryObject result))
  return result;

// Setting the object in the cache:
cache.SetValue(cacheKey, objectToCache);

WHAT IT IS WITH THE SIZELIMIT PROPERTY?

Once you create a new instance of a MemoryCache, you need to specify a sizelimit. In bytes? Kb? Mb? No, the SizeLimit is not an amount of bytes, but a number of cache entries your cache might hold.

Each cache entry you insert must specify a size (integer). The MemoryCache will then hold entries until that limit is met.

Example:

  • I specify a SizeLimit of 100.
  • I can then insert 100 entries with size = 1, or 50 entries with size = 2.
  • You can of course insert entries in different sizes, and when the sum reaches the SizeLimit, no more entries are being inserted.

The idea is that you know which entries are small and which are large, and you then control the memory usage of your cache this way, instead of having a hard ram-based limit.

Btw, if there is no more room in the cache, it is not the oldest entry that is being removed, making room for the new one. Instead, the new entry is not inserted, and the Set() method does not fail.

WHEN ARE ITEMS REMOVED FROM THE CACHE?

For each entry you specify the expiration time. In the example above, I use AbsoluteExpiration, but you can also use SlidingExpiration, or set a Priority. And you can even pin entries using the Priority = NeverRemove.

The actual entry is not removed with a background process, but rather when any activity on the cache is performed.

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in .net, .NET Core, c# and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.