Я недавно изучил некоторую.NET "утечки памяти" (т.е. неожиданный, непрекращающийся GC базировался объекты) в приложении WinForms. После загрузки и затем закрытия огромного отчета, использование памяти не отбрасывало как ожидалось даже после нескольких gen2 наборов. Предположение, что управление созданием отчетов поддерживалось случайным обработчиком событий, я взломал WinDbg для наблюдения то, что происходило...
Использование WinDbg, !dumpheap -stat
команда сообщила, что большой объем памяти был использован строковыми экземплярами. Далее совершенствовав это вниз с !dumpheap -type System.String
управляйте, чтобы я нашел преступника, строка 90 МБ используемый для отчета, в адресе 03be7930. Последний шаг должен был вызвать !gcroot 03be7930
видеть, какой объект (объекты) поддерживал его.
Мои ожидания были неправильными - это не был отсоединенный обработчик событий, зависающий на управление созданием отчетов (и строка отчета), но вместо этого это состоялось a System.Text.RegularExpressions.RegexInterpreter
экземпляр, который сам является потомком a System.Text.RegularExpressions.CachedCodeEntry
. Теперь, кэширование Regexs является (несколько) общепринятой истиной, поскольку это помогает уменьшить издержки необходимости перекомпилировать Regex каждый раз, когда это используется. Но что затем это имеет отношение к поддержанию моей строки?
На основе анализа с помощью Отражателя оказывается, что входная строка хранится в RegexInterpreter каждый раз, когда метод Regex называют. RegexInterpreter содержит на эту строковую ссылку, пока новая строка не питается в него последующим вызовом метода Regex. Я ожидал бы подобное поведение путем зависания на Regex. Экземпляры соответствия и возможно другие. Цепочка - что-то вроде этого:
Оскорбление Regex только используется для создания отчетов, редко используемое, и поэтому вряд ли использоваться снова для убирания существующей строки отчета. И даже если бы Regex использовался позже, то он, вероятно, обработал бы другой большой отчет. Это - относительно значительная проблема и просто чувствует себя грязным.
Однако я нашел несколько опций о том, как решить, или по крайней мере работать вокруг, этот сценарий. Я позволю сообществу ответить сначала и если никакие берущие не выступят вперед, то я заполню любые разрывы через день или два.
Используете ли вы экземпляры Regex или статические методы Regex, которые принимают шаблон строки? Согласно этому сообщению , экземпляры Regex не участвуют в кешировании.
Попробуйте переключиться на скомпилированное регулярное выражение - создание экземпляра займет больше времени, но, возможно, не будет подвержено этой странной утечке.
См. http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regexoptions%28v=VS.100%29.aspx для получения дополнительной информации.
Или не держите экземпляр Regex дольше, чем нужно - создавайте новый для каждого вызова отчета.