メモリ内の単純なキャッシュ

こんにちは





データベースに再び入らないように、非常に原始的なキャッシュを作成するのにここでかかりました。 同時に、データベース内のデータは静的であり、問​​題はデータを更新することではなく、メモリを占有しないためにいつ破棄するかということであり、もちろん使いやすさが重要です。 最初はMemoryCacheを使用したかったのですが、私にはあまりにも混乱しているようで、厳密な入力もしていませんでした。



catでの実装例をお願いします。





実装


一般的な考え方は次のとおりです。キャッシュは使いやすく、透過的に使用する必要があります。 ThreadLocalクラスのインターフェースに触発されました。 そのため、コンストラクターは元の値を取得するためにファクトリーメソッドを必要とし、その後、それらは既にキャッシュされています。 繰り返しますが、私の場合、データを弱いリンク(WeakReference)に保持することは論理的であると考えたため、データが必要なときに誰かがそれを使用し、利用可能になります。 さらに、新しいメモリが割り当てられると、キャッシュからのデータが強制的に削除されます。

メソッドは2つしかありません。ソースまたはキャッシュからデータを返すインデクサーです。

CleanCacheメソッドと同様に、デッドリンクの辞書をクリアして、メモリリークを排除します。 実際の状況では、これは常に必要というわけではありません。 たとえば、私の状況では、キャッシュ内の新しいエントリは1日に数回しか表示されないため、長年の操作でも、リンクが大量のメモリを消費することはありません。



出版の目的


基本的に、私は私の実装についての意見を聞くことに興味があります。エラーがあればどうしますか。 まあ、これが誰かを助けるなら-それを取り、それを使用してください:)



ソースコード




public class WeakCache<TKey,TValue> where TValue : class { const int cacheCleanInterval = 60; private readonly Func<TKey, TValue> getter; private readonly Dictionary<TKey, WeakReference> data = new Dictionary<TKey, WeakReference>(); private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim(); private DateTime lastCacheClean = DateTime.MinValue; public WeakCache(Func<TKey,TValue> getter) { this.getter = getter; } public TValue this[TKey key] { get { CleanCache(); try { rwLock.EnterUpgradeableReadLock(); WeakReference wr; TValue val; if (data.TryGetValue(key, out wr)) { val = (TValue)wr.Target; if (val != null) return val; } try { rwLock.EnterWriteLock(); if (data.TryGetValue(key, out wr)) { val = (TValue)wr.Target; if (val != null) return val; } data[key] = new WeakReference(val = getter(key)); return val; } finally { rwLock.ExitWriteLock(); } } finally { rwLock.ExitUpgradeableReadLock(); } } } void CleanCache() { if ((DateTime.Now - lastCacheClean).TotalSeconds > cacheCleanInterval) { try { rwLock.EnterWriteLock(); if ((DateTime.Now - lastCacheClean).TotalSeconds > cacheCleanInterval) { lastCacheClean = DateTime.Now; var refs = data.ToArray(); foreach (var weakReference in refs) { if (!weakReference.Value.IsAlive) data.Remove(weakReference.Key); } } } finally { rwLock.ExitWriteLock(); } } } }
      
      






All Articles