8

To be succinct, what SIMPLE In-Memory Caches exist in the .Net ecosystem?

What I am looking for is:

  • No-configuration (other than simple API calls). I do not want to mess with external configuration files as they just complicate deployment.
  • Same-process (not some external process or server). Preferrably created as easily as
    var myCache = new SimpleCache(1024 * 1024 * 100); // 100 MB
  • Specified Memory limit
  • Items cleared from cache based on least usage
  • Time-based expiration (not required, but makes it potentially useful in other scenarios)
  • Works with .Net 3.5

I have already reasearched these options:

  • ASP.Net System.Web.Caching
    • Its API does not support any sort of control over the size of the cache, nor priority based on usage. Consequently you are entirely at its mercy as to when it decides there is enough memory pressure to empty out the cache.
  • System.Runtime.Caching
  • Microsoft Enterprise Library - Caching Block
    • Other than having a reputation of being heavyweight, I do not like its configuration using XML files or app.config. Furthermore, while it supports limiting the size of the cache based on NUMBER of objects stored, it does not have mechanisms for limiting the SIZE of those objects.
  • NCache
    • Probably overkill for the use case I want, but most importantly it is a paid product which is not something I want to do deal with (compared with me just writing one in a day or two). As usual, its express edition has usage limitations discouraging its use for any production purposes.
  • MemCacheD
    • Exact opposite of what I want (External distributed process)

I am working with Google Protocol Buffers (protobuf-net), so I DO have a relatively accurate estimation of the memory footprint of each item. I am caching data returned from database access, but I have no desire to use a formal ORM (I am actually using PetaPoco, but that is beside the point).

At this stage I am planning on implementing my own cache, using a double linked list and hash (dictionary) to provide for dropping items that are least recently used from the cache once the cache limit is reached. However, I wanted to check to see if anyone knew of any suitable options before I rolled my own.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Matt G
  • 437
  • 3
  • 9
  • 1
    This is just never simple, a cache without a good expiration policy is a memory leak. Not liking what's available is always motivation number one to build your own. – Hans Passant Jun 11 '12 at 18:32
  • Instead of an expiration policy, I want to specify a maximum amount of memory it should take up. You cannot really measure how much memory objects are taking up in .Net, but the protocol buffers I am using have a reasonably useful measurement. – Matt G Jun 11 '12 at 18:47
  • If you develop this to be a fairly generic cache, then perhaps you could put it on CodeProject or the like, for others to use? Should be fairly straightforward to get a simple prototype together and be very simple to get high test coverage. – Mike Jun 11 '12 at 21:47
  • The link by Mare Infinitus http://www.codeproject.com/Articles/7684/Using-C-Generics-to-implement-a-Cache-collection is what I used as a basis. I may have cause to make it more generic in the future, but between it being a specific-use-case (not using generics currently), and it being my employer's Intellectual Property, I doubt I will put it on CodeProject. – Matt G Jun 12 '12 at 18:03

4 Answers4

3

So what did you end up doing with the cache?

I have a prototype of Universal Cache that I was working on that does pretty much what you want except the cache limit is by capacity (number of items) instead of memory usage but it has an extra feature that you may appreciate: local persistence.

The cache is structured by layer where you can have a single layer: memory, a double layer: memory + local persistence, or a triple layer: memory + local persistence + network sharing. You can use any combination of layers as you need. Although the network sharing that is designed as a .net remoting service that can be installed on any computer on the network and is self-discoverable by client caches is not quite functional yet.

The caches are generic classes accessed via an interface ICache<TKey,TValue>. The local persistent cache use SQL Express Compact 4 to create on-the-fly database and tables that have all the fields of your TKey, a timestamp, and a TValue that is serialized as an Image column. In case of multiple layer configuration, when you use the method TryGetValue( TKey key, out TValue value ) on the top level cache, if the first layer (memory cache) doesn't have the item it check internally with the next layer (local persistent), then the next... until no more cache are available to provide the data. When the memory cache discards an item, it let the next cache the opprtunity to add the item to its layer so in case of persistent cache the data is stored for future requests.

The caches have a use-defined retention time parameter (i.e. few minutes for a memory cache, 30 days for local persistent cache) and capacity.

I may post it as public domain code if someone is interested.

ML64
  • 31
  • 3
1

What about the caching features in AppFabric for Windows Server ? Give it a try ! http://msdn.microsoft.com/en-us/windowsserver/ee695849.aspx and http://msdn.microsoft.com/en-us/library/hh334364.aspx

But if there are no products on the market that provide the wanted behavior, you will have to implement your own custom caching layer using Design Patterns.

Jason De Oliveira
  • 1,732
  • 9
  • 16
  • It is nice to see an option that I had not already considered, and also nice that even though it looks geared towards XML configuration, it has equivalent programmatic configuration options. However, it is not what I am looking for as it appears to provide no capabilities for limiting based on memory usage. Limiting a cache by object count is rather useless because those objects could be the root of tress consuming 1 KB each or 1 GB each. – Matt G Jun 12 '12 at 17:58
1

It is quite old, but i resembles what you are talking about

Generic cache with memory consumption

and here is another SO with a relevant scenario:

performance of system runtime caches

Community
  • 1
  • 1
Mare Infinitus
  • 8,024
  • 8
  • 64
  • 113
  • +1 because this is actually the article I read two months ago that provided the basis for designing my own. I have not looked at the full source code, but the article was a good starting point. – Matt G Jun 12 '12 at 18:00
0

Check the MemoryCache and this article on CodeProject about using MemoryCache.

Khachatur
  • 921
  • 1
  • 12
  • 30