[banshee: 3/12] [LruCache] Add HitRatio and min hit ratio ability



commit b2fd1a071956fe9ec6524ecae2997076bcf40ec2
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Thu Jul 23 14:24:30 2009 -0700

    [LruCache] Add HitRatio and min hit ratio ability
    
    You can (optionally) set a desired minimum hit ratio, and the cache will
    grow in size if that ratio isn't being met (presumably because things
    were being evicted)

 src/Libraries/Hyena/Hyena.Collections/LruCache.cs |   52 +++++++++++++++++++-
 1 files changed, 49 insertions(+), 3 deletions(-)
---
diff --git a/src/Libraries/Hyena/Hyena.Collections/LruCache.cs b/src/Libraries/Hyena/Hyena.Collections/LruCache.cs
index 7520e03..b644bea 100644
--- a/src/Libraries/Hyena/Hyena.Collections/LruCache.cs
+++ b/src/Libraries/Hyena/Hyena.Collections/LruCache.cs
@@ -54,17 +54,25 @@ namespace Hyena.Collections
     {
         private Dictionary<TKey, CacheEntry<TKey, TValue>> cache;
         private int max_count;
-        
+        private long hits;
+        private long misses;
+        private double? minimum_hit_ratio;
+
         public LruCache () : this (1024)
         {
         }
         
-        public LruCache (int maxCount)
+        public LruCache (int maxCount) : this (maxCount, null)
+        {
+        }
+
+        public LruCache (int maxCount, double? minimumHitRatio)
         {
             max_count = maxCount;
+            minimum_hit_ratio = minimumHitRatio;
             cache = new Dictionary<TKey, CacheEntry<TKey, TValue>> ();
         }
-        
+
         public void Add (TKey key, TValue value)
         {
             lock (cache) {
@@ -79,6 +87,9 @@ namespace Hyena.Collections
                 entry.Value = value;
                 Ref (ref entry);
                 cache.Add (key, entry);
+
+                misses++;
+                EnsureMinimumHitRatio ();
                 
                 if (Count >= max_count) {
                     TKey expire = FindOldestEntry ();
@@ -94,6 +105,16 @@ namespace Hyena.Collections
                 return cache.ContainsKey (key);
             }
         }
+
+        public void Remove (TKey key)
+        {
+            lock (cache) {
+                if (Contains (key)) {
+                    ExpireItem (cache[key].Value);
+                    cache.Remove (key);
+                }
+            }
+        }
         
         public bool TryGetValue (TKey key, out TValue value)
         {
@@ -103,13 +124,23 @@ namespace Hyena.Collections
                     value = entry.Value;
                     Ref (ref entry);
                     cache[key] = entry;
+                    hits++;
                     return true;
                 }
                 
+                misses++;
+                EnsureMinimumHitRatio ();
                 value = default (TValue);
                 return false;
             }
         }
+
+        private void EnsureMinimumHitRatio ()
+        {
+            if (minimum_hit_ratio != null && Count >= MaxCount && HitRatio < minimum_hit_ratio) {
+                MaxCount = Count + 1;
+            }
+        }
         
         private void Ref (ref CacheEntry<TKey, TValue> entry)
         {
@@ -163,5 +194,20 @@ namespace Hyena.Collections
         public int Count {
             get { lock (cache) { return cache.Count; } }
         }
+
+        public double? MinimumHitRatio { get { return minimum_hit_ratio; } }
+
+        public long Hits { get { return hits; } }
+        public long Misses { get { return misses; } }
+
+        public double HitRatio {
+            get {
+                if (misses == 0) {
+                    return 1.0;
+                } else {
+                    return ((double)hits) / ((double)(hits + misses));
+                }
+            }
+        }
     }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]