Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object cache for C#

Tags:

I'm doing a document viewer for some document format. To make it easier, let's say this is a PDF viewer, a Desktop application. One requirement for the software is the speed in rendering. So, right now, I'm caching the image for the next pages while the user is scrolling through the document.

This works, the UI is very responsive and it seems like the application is able to render the pages almost instantly....at a cost : the memory usage sometimes goes to 600MB. I cache it all in memory.

Now, I can cache to disk, I know, but doing that all the time is noticeably slower. What I would like to do is implement some cache (LRU?), where some of the cached pages (image objects) are on memory and most of them are on disk.

Before I embark on this, is there something in the framework or some library out there that will do this for me? It seems a pretty common enough problem. (This is a desktop application, not ASP.NET)

Alternatively, do you have other ideas for this problem?

like image 314
moogs Avatar asked Feb 24 '09 09:02

moogs


People also ask

What is caching in C?

Caching is a separate memory, yes, and it has it's own addresses, but when the CPU caches memory lines from RAM, it keeps a record of what RAM-addresses the memory was on, and keeps a map between RAM-address and cache-address. From the point of view of your program, the address is the same.

What are cache objects?

An object cache is a recently used object definition stored in memory on Developer and Intelligence Server. You browse an object definition when you open the editor for that object. You can create object caches for applications.

How do I enable object cache?

If you're good to go, this plugin is super simple to install—just activate the plugin, go to Settings > Redis and click “Enable Object Cache.” If you run into any problems, again, you'll need to check with your web host whether the server your site is hosted on is set up for Redis.

What is cache in programming?

In computing, a cache is a high-speed data storage layer which stores a subset of data, typically transient in nature, so that future requests for that data are served up faster than is possible by accessing the data's primary storage location.


2 Answers

I wrote an LRU Cache and some test cases, feel free to use it.

You can read through the source on my blog.

For the lazy (here it is minus the test cases):

using System; using System.Collections.Generic; using System.Linq; using System.Text;  namespace LRUCache {     public class IndexedLinkedList<T> {          LinkedList<T> data = new LinkedList<T>();         Dictionary<T, LinkedListNode<T>> index = new Dictionary<T, LinkedListNode<T>>();          public void Add(T value) {             index[value] = data.AddLast(value);         }          public void RemoveFirst() {             index.Remove(data.First.Value);             data.RemoveFirst();         }          public void Remove(T value) {             LinkedListNode<T> node;             if (index.TryGetValue(value, out node)) {                 data.Remove(node);                 index.Remove(value);             }         }          public int Count {             get {                 return data.Count;             }         }          public void Clear() {             data.Clear();             index.Clear();         }          public T First {             get {                 return data.First.Value;             }         }     } } 

LRUCache

using System; using System.Collections.Generic; using System.Linq; using System.Text;  namespace LRUCache {     public class LRUCache<TKey, TValue> : IDictionary<TKey, TValue> {          object sync = new object();         Dictionary<TKey, TValue> data;         IndexedLinkedList<TKey> lruList = new IndexedLinkedList<TKey>();         ICollection<KeyValuePair<TKey, TValue>> dataAsCollection;         int capacity;          public LRUCache(int capacity) {              if (capacity <= 0) {                 throw new ArgumentException("capacity should always be bigger than 0");             }              data = new Dictionary<TKey, TValue>(capacity);             dataAsCollection = data;             this.capacity = capacity;         }          public void Add(TKey key, TValue value) {             if (!ContainsKey(key)) {                 this[key] = value;             } else {                 throw new ArgumentException("An attempt was made to insert a duplicate key in the cache.");             }         }          public bool ContainsKey(TKey key) {             return data.ContainsKey(key);         }          public ICollection<TKey> Keys {             get {                 return data.Keys;             }         }          public bool Remove(TKey key) {             bool existed = data.Remove(key);             lruList.Remove(key);             return existed;         }          public bool TryGetValue(TKey key, out TValue value) {             return data.TryGetValue(key, out value);         }          public ICollection<TValue> Values {             get { return data.Values; }         }          public TValue this[TKey key] {             get {                 var value = data[key];                 lruList.Remove(key);                 lruList.Add(key);                 return value;             }             set {                 data[key] = value;                 lruList.Remove(key);                 lruList.Add(key);                  if (data.Count > capacity) {                     data.Remove(lruList.First);                     lruList.RemoveFirst();                 }             }         }          public void Add(KeyValuePair<TKey, TValue> item) {             Add(item.Key, item.Value);         }          public void Clear() {             data.Clear();             lruList.Clear();         }          public bool Contains(KeyValuePair<TKey, TValue> item) {             return dataAsCollection.Contains(item);         }          public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {             dataAsCollection.CopyTo(array, arrayIndex);         }          public int Count {             get { return data.Count; }         }          public bool IsReadOnly {             get { return false; }         }          public bool Remove(KeyValuePair<TKey, TValue> item) {              bool removed = dataAsCollection.Remove(item);             if (removed) {                 lruList.Remove(item.Key);             }             return removed;         }           public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {             return dataAsCollection.GetEnumerator();         }           System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {             return ((System.Collections.IEnumerable)data).GetEnumerator();         }      } } 
like image 91
Sam Saffron Avatar answered Oct 05 '22 07:10

Sam Saffron


For .NET 4.0, you can also use the MemoryCache from System.Runtime.Caching.

http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx

like image 25
rsbarro Avatar answered Oct 05 '22 07:10

rsbarro