最近我接手了一个WCF Windows Service,它大量使用以下静态实用程序类来检索查找数据:
public static class Utility
{
//begin code that causes increased memory consumption
private static Dictionary<string, ErrorData> _errorData;
internal static Dictionary<string, ErrorData> ErrorData
{
get
{
if (_errorData == null)
{
_errorData = GetErrorData();
}
return _errorData;
}
}
//end code that causes increased memory consumption
/// GetErrorData method to get error messages from error xml
/// </summary>
/// <returns>Dictionary of Error messages value for different fields.</returns>
internal static Dictionary<string, ErrorData> GetErrorData()
{
Dictionary<string, ErrorData> data = null;
XmlDocument doc = LoadXmlDocument(Constants.ErrorMessagesFileName);
XmlNodeList errorNode = doc.SelectNodes("/ErrorMessages/Error");
data = new Dictionary<string, ErrorData>();
foreach (XmlNode node in errorNode)
{
ErrorData errorValues = new ErrorData();
errorValues.FieldName = node.Attributes["FieldName"].Value;
errorValues.ErrorMessage = node.Attributes["ErrorMessage"].Value;
data.Add(node.Attributes["code"].Value, errorValues);
}
return data;
}
internal static XmlDocument LoadXmlDocument(string xmlFileName)
{
XmlDocument doc = null;
try
{
if (HttpRuntime.Cache[xmlFileName] == null)
{
doc = new XmlDocument();
doc.Load(Constants.Folderpath + "\\" + xmlFileName);
HttpRuntime.Cache.Insert(xmlFileName, doc);
}
else
{
doc = (XmlDocument)HttpRuntime.Cache[xmlFileName];
}
}
catch (Exception ex)
{
//log
}
return doc;
}
}
正如您所看到的,静态 ErrorData 属性使用了一个私有的后备字段。ErrorData 是一个字典,它是使用文件系统上的 XML 资源构建的,这就是为什么文件的内容在初始检索时存储在 HttpRuntime.Cache 中的原因。
在正常负载下,该服务大约消耗 120MB 的 RAM。
在某个时候,团队成员感觉需要引入另一级优化,通过创建由懒加载静态字段支持的静态属性来实现。无论如何,存在该静态字段会导致内存泄漏(500MB+),仅在调用几次服务后就会出现。
一旦我删除静态字段和属性(客户端改为调用 Utility.GetErrorData()),内存消耗就会恢复到正常水平。
有人能解释一下为什么存在这个静态字段会导致内存泄漏吗?如果有区别的话,WCF 服务正在运行 InstanceContextMode.PerCall。
非常感谢。