почему этот код вызывает утечку памяти?

Недавно я стал владельцем службы Windows WCF, которая интенсивно использует следующий статический класс Utility для получения поиска data:

   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.

При нормальной нагрузке служба потребляет около 120 МБ ОЗУ.

В какой-то момент член команды почувствовал необходимость ввести другой уровень оптимизации, создав статическое свойство, поддерживаемое лениво загруженным статическим полем. В любом случае наличие указанного статического поля вызывает довольно серьезную утечку памяти (более 500 МБ) после нескольких обращений к службе.

В ту минуту, когда я удаляю статическое поле и свойство (вместо этого клиенты вызывают Utility.GetErrorData ()), потребление памяти возвращается к нормальному уровню.

Может ли кто-нибудь объяснить, почему присутствие этого статического поля вызывает утечку памяти? Служба WCF работает с InstanceContextMode.PerCall, если это имеет значение.

Большое спасибо.

8
задан Hans Gruber 7 June 2011 в 02:16
поделиться