技术开发 频道

谈表达式树的缓存:使用前缀树

    再编写PrefixTreeCache之前,我们可能还需要准备它的读取与写入功能。这两个操作其实都是对PrefixTreeVisitor的简单封装:

public class PrefixTreeCache<T> : IExpressionCache<T> where T : class
{
private Hashtable m_storage = new Hashtable();

private T Get(Expression key)
{
var visitor = new PrefixTreeVisitor(this.m_storage, true);
var storage = visitor.Accept(key);
return storage == null ? null : (T)storage[typeof(T)];
}

private void Set(Expression key, T value)
{
var visitor = new PrefixTreeVisitor(this.m_storage, false);
var storage = visitor.Accept(key);
storage[typeof(T)] = value;
}
}
  现在编写IExpressionCache.Get方法已如探囊取物:

private ReaderWriterLockSlim m_rwLock = new ReaderWriterLockSlim();

public T Get(Expression key, Func<Expression, T> creator)
{
T value;

this.m_rwLock.EnterReadLock();
try
{
value = this.Get(key);
if (value != null) return value;
}
finally
{
this.m_rwLock.ExitReadLock();
}

this.m_rwLock.EnterWriteLock();
try
{
value = this.Get(key);
if (value != null) return value;

value = creator(key);
this.Set(key, value);
return value;
}
finally
{
this.m_rwLock.ExitWriteLock();
}
}
 

    使用前缀树缓存方式,在已有n个对象的缓存容器中查询带有m个节点的表达式树,其时间复杂度正如之前所谈到那样为O(m)——与n无关。这个解决方案的缺点在于构造了大量的Hashtable,可能会导致整个前缀树处于一种非常稀疏的状态,这点可以通过自定义查找方式来替换直接使用Hashtable类进行优化。这属于纯粹的进一步实践,感兴趣的朋友可以自己尝试一下。

原文地址:http://www.cnblogs.com/jeffreyzhao/archive/2009/03/18/expression-cache-3-prefix-tree-cache.html

0
相关文章