首页 > 代码库 > 转 一个弱引用缓存类
转 一个弱引用缓存类
在优化性能时,经常会使用到缓存类。.NET Framework在System.Web.dll中,提供了一个Cache类。它在Web开发中非常有用,但是如果是WinForm开发,它就用不上了。
在.NET中,由于垃圾回收机制的存在,使得开发人员不用关心内存的分配。不用的对象GC会自动当成垃圾回收。如果能将这些垃圾废品利用的话,很容易节约开销,提升性能。
下面提供一个WeakReferenceCachePool<TKey, TItem>类:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.ConstrainedExecution;
namespace CacheDemo
{
#region The WeakReferenceCachePool<TKey, TItem> class
public class WeakReferenceCachePool<TKey, TItem> where TItem : class
{
#region The Cleaner class
private class Cleaner : CriticalFinalizerObject
{
#region Instance Data
private WeakReferenceCachePool<TKey, TItem> _owner;
#endregion
#region Constructor & Finalizer
public Cleaner(WeakReferenceCachePool<TKey, TItem> owner)
{
this._owner = owner;
}
~Cleaner()
{
if (this._owner._autoCleanAbandonedItems)
{
this._owner.CleanAbandonedItems();
GC.ReRegisterForFinalize(this);
}
}
#endregion
}
#endregion
#region Instance Data
private const int LOCK_TIMEOUT_MSECS = 500;
private Dictionary<TKey, WeakReference> _cachePool;
private bool _autoCleanAbandonedItems;
private ReaderWriterLockSlim _cacheLock;
#endregion
#region Constructor & Finalizer
public WeakReferenceCachePool() : this(true) { }
public WeakReferenceCachePool(bool autoCleanAbandonedItems)
{
this._cacheLock = new ReaderWriterLockSlim();
this._cachePool = new Dictionary<TKey, WeakReference>();
this._autoCleanAbandonedItems = autoCleanAbandonedItems;
if (this._autoCleanAbandonedItems)
{
new Cleaner(this);
}
else
{
GC.SuppressFinalize(this);
}
}
~WeakReferenceCachePool()
{
this._autoCleanAbandonedItems = false;
}
#endregion
#region Properties
public bool AutoCleanAbandonedItems
{
get
{
return this._autoCleanAbandonedItems;
}
}
public TItem this[TKey key]
{
get
{
if (key == null)
{
throw new ArgumentNullException("key");
}
if (this._cacheLock.TryEnterReadLock(LOCK_TIMEOUT_MSECS))
{
try
{
WeakReference weakReference;
if (_cachePool.TryGetValue(key, out weakReference))
{
return (TItem)weakReference.Target;
}
}
finally
{
this._cacheLock.ExitReadLock();
}
}
return null;
}
set
{
this.Add(key, value);
}
}
#endregion
#region Methods
public void Add(TKey key, TItem item)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
if (item == null)
{
throw new ArgumentNullException("item");
}
if (this._cacheLock.TryEnterWriteLock(LOCK_TIMEOUT_MSECS))
{
try
{
_cachePool[key] = new WeakReference(item);
}
finally
{
this._cacheLock.ExitWriteLock();
}
}
}
public void Remove(TKey key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
if (this._cacheLock.TryEnterWriteLock(LOCK_TIMEOUT_MSECS))
{
try
{
this._cachePool.Remove(key);
}
finally
{
this._cacheLock.ExitWriteLock();
}
}
}
public void Clear()
{
if (this._cacheLock.TryEnterWriteLock(LOCK_TIMEOUT_MSECS))
{
try
{
this._cachePool.Clear();
}
finally
{
this._cacheLock.ExitWriteLock();
}
}
}
public void CleanAbandonedItems()
{
if (this._cacheLock.TryEnterWriteLock(LOCK_TIMEOUT_MSECS))
{
try
{
Dictionary<TKey, WeakReference> newCachePool = new Dictionary<TKey, WeakReference>();
foreach (KeyValuePair<TKey, WeakReference> keyValuePair in _cachePool)
{
if (keyValuePair.Value.IsAlive)
{
newCachePool[keyValuePair.Key] = keyValuePair.Value;
}
}
this._cachePool = newCachePool;
}
finally
{
this._cacheLock.ExitWriteLock();
}
}
}
#endregion
}
#endregion
}
以下是我总结的利用WeakReference做缓存带来的好处和坏处,欢迎拍砖。。。
利用WeakReference做缓存可能带来以下好处:
1,与普通缓存一样,能带来的性能提升
2,不会影响缓存对象被垃圾回收
3,由于是废品利用,可以说不用多占内存,即节约内存
4,由于GC回收机制的存在,能自动处理内存占用与性能间的平衡
5,其他。。。
利用WeakReference做缓存可能带来以下坏处:
1,命中率受GC回收机制影响,不确定
2,其他。。。
另,这篇文章正好是使用WeakReference做缓存的一个例子《一次性能提升300%的优化实践》。
小Tip:
可以适当地使用 GC.KeepAlive(cachedObject)来避免cachedObject 被GC回收。
-------------
p.s.
cachedObject 就是被WeakReference track 的那个,比如:
WeakReference wf = new WeakReference(cachedObject);
转 一个弱引用缓存类
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。