public TValue Get(TKey key, CacheFallBack <TKey, TValue> fallback) { lock (mLocker) { #if TEST TotalFetch++; #endif if (mDictionary.TryGetValue(key, out TValue value)) { #if TEST HitCount++; #endif UpdateCounter(key); return(value); } if (fallback == null) { throw new ArgumentNullException(nameof(fallback)); } CacheValue <TValue> cacheValue = fallback(key); if (!cacheValue.AddToCache) { return(cacheValue.Value); } TValue result = cacheValue.Value; Counter currentCounter; if (mDictionary.Count >= mCapacity) { mDictionary.Remove(mMaxKey); mUsageCounters.Remove(mMaxKey); currentCounter = mMaxCounter; currentCounter.Reset(); IncreaseAllCounters(); FindMaxKey(); mDictionary.Add(key, result); mUsageCounters.Add(key, currentCounter); } else { IncreaseAllCounters(); FindMaxKey(); mDictionary.Add(key, result); currentCounter = mCounterPool.Pop(); currentCounter.Reset(); mUsageCounters.Add(key, currentCounter); } return(result); } }
public void TestCache() { CacheFallBack <string, string> fallback = (key) => CacheValue <string> .From(key); int times = 500; List <string> data = GenerateData(100); ICache <string, string> cache = new Cache <string, string>(50); Random random = new Random(Guid.NewGuid().GetHashCode()); while (times > 0) { int index = random.Next(0, data.Count); string input = data[index]; string result = cache.Get(input, fallback); Assert.AreEqual(input, result); times--; } int total = cache.TotalFetch; int hit = cache.HitCount; Console.WriteLine($"Hit rate: {hit * 1.0 / total}"); }