最近因需要网站采用了Xml+Xsl来输出html片段的方案,XslCompiledTransform类提供了xsl转换,而且XslCompiledTransform实例的Transform方法是线程安全的。
由于.Net2.0中的XslCompiledTransform采用了xsl动态编译,相对Net1.0中的XslTransform性能提高很大,但是它在第一次加载并编译xsl模板时速度很慢,所以需要全局维持一个静态的XslCompiledTransform实例。但是问题是,如果网站访问并发性高的话,一个静态实例就应付不过来,最后想了一个方法解决,实现原理上模拟“池”的概念:
首先提供一个盒子类,容纳N个XslCompiledTransform实例,索引在静态成员变量Hashtable中
public class HoldBox<T>
{
int _maxHold = 1;//最大容量
int _count = 0;//当前容量
int _current = -1;//之后一次调配的项目座次号
Hashtable _Box = new Hashtable();
//
public HoldBox()
{
}
public HoldBox(int maxHold)
{
_maxHold = maxHold;
}
//判断盒子是否能再添加缓存项
public bool CanAppended {
get {
return _Box.Count < _maxHold;
}
}
//添加缓存项
public void Append(T aObj)
{
_Box[_count.ToString()] = aObj;
_count++;
}
//外部客户端请求一个缓存项输出
public T GetOne()
{
if (_count > 0)
{
_current++;
_current = _current % _count;
return (T)(_Box[_current.ToString()]);
}
else
{
throw new Exception("HoldBox尚未包含有效对象!");
}
}
public void Empty()
{
for (int i = _maxHold; i > -1; i--) {
_Box[i.ToString()] = null;
}
System.GC.Collect();
}
public int Count {
get {
return _Box.Count;
}
}
}
客户端代码:
首先初始化盒子
en_XslHoldBox = new HoldBox<XslCompiledTransform>(12);
while (en_XslHoldBox.CanAppended)
{
string xslfile = GetXslFileName(language);
XslCompiledTransform trans = new XslCompiledTransform();
trans.Load(xslfile, new XsltSettings(false, true), null);
en_XslHoldBox.Append(trans);
}
上面代码一共内建了12个XslCompiledTransform实例供调用
接下来,在Xml转换时只要调用:
....
//向盒子请求一个XslCompiledTransform实例
XslCompiledTransform RssXslt = en_XslHoldBox.GetOne();
//Xml转换并输出
....
增加并发性能的关键是盒子类中预存了多个XslCompiledTransform实例,随后按照一个轮询的次序依次为客户端委派实例。这样连续的请求就可以均匀的分配,不至于阻塞在一个XslCompiledTransform实例上。
小小心得,供参考,有不足之处大家尽管拍砖 :)
不知道大家遇到类似问题时,是用什么方法解决的。都来说说吧,有更好方案的也欢迎例举