Национальный Аэрокосмический Университет им. Н.Е. Жуковского „Харьковский авиационный институт” Кафедра Компьютерных Систем и Сетей Обнаружение и устранение утечек памяти на платформе .NET Автор доклада: студент гр. 555аМ Коплик А.В. Харьков 2014 Рассматриваемые вопросы: Память в .NET приложениях: управляемая и неуправляемая Способы обнаружения утечек памяти Борьба с утечкой памяти на реальном проекте Коплик А.В. 555ам 2 Memory leak: Утечки памяти – кошмары программистов Проблема утечки памяти – вред для производственных серверов Утечки памяти в управляемом коде невозможны? Garbage Collector (уборщик мусора) – так ли хорош Взаимодействие с неуправляемым кодом Коплик А.В. 545а 3 Память в .Net приложениях: Стек – локальные переменные, параметры методов, возвращаемые значения, временные данные. GC не отвечает за его очистку. Хранение ссылок на объекты в куче Неуправляемая куча – структуры данных времени выполнения, таблицы методов, MSIL, код прошедший JIT и т.д. Управляемая куча памяти – область размещения управляемых объектов и их обработки garbage collector-ом. GC основывается на поколениях объектов, переживших сборку мусора. Gen0, Gen1, и Gen2 (от самых молодых до самых старых). Коплик А.В. 545а 4 Обнаружение утечек памяти: Первоочередная задача – подтвердить, что есть утечка памяти. Но использование диспетчера задач не поможет в этом, т.к. не даёт информации о нахождении утечки памяти и вводит в заблуждение Коплик А.В. 545а 5 Причина лживости Task Manager: Менеджер задач показывает рабочий набор памяти , а не фактический объем используемой памяти Память, выделяемая в дальнейшем из рабочего набора может быть разделена между процессами/приложения ми Коплик А.В. 545а 6 Ловля утечки памяти на проекте: Проект развёрнут на IIS. Отслеживается процесс w3wp.exe Чтобы получить правильное количество потребляемо памяти – нужно отследить счётчик Private Bytes – это те области памяти, которые не задействуются другими приложениями. Необходимо запустить счётчик Private Bytes монитора производительности Cmd > perfmon -> добавить счетчик Process ->‘Private bytes’ Коплик А.В. 545а 7 Суть проекта: ASMX сервис для генерации отчётов Вызов Generate PDF много раз ( > 300) приводит к утечке памяти Коплик А.В. 545а 8 Performance monitor: Коплик А.В. 545а На графике видно что потребление Private Bytes резко возросло что говорит о том, что утечка памяти спрятана именно в генерации PDF 1 этап пройден – мы подтвердили утечку памяти, самое время – определить её источник 9 3 шага исследования утечки: Определить тип утечки – утечка в управляемой или неуправляемой памяти Определить что действительно является причиной утечки, это объект соединения или незакрытый handler какого-то файла Найти функцию или метод, который вызывает утечку Управляемая память контролируется сборщиком мусора, а неуправляемая – нет. Чтобы понять вид памяти, в которой произошла утечка – нужно воспользоваться двумя счётчиками (Private bytes + Bytes In all heaps) Коплик А.В. 545а 10 Private bytes: Private bytes – это общее количество памяти, потребляемой приложением. Private bytes = Неуправляемая память + байты во всех кучах Если количество приватных байтов растёт, а количество байт во всех кучах неизменно – мы имеем утечку неуправляемой памяти Если количество байт во всех кучах растёт линейно – это значит что мы имеем утечку в управляемой памяти Коплик А.В. 545а 11 Пример утечки неуправляемой памяти Количество приватных байтов возрастает, в то время как байты в кучах остаются практически неизменными. Здесь также видно, что Байты во всех кучах также возрастают. Это говорит о возможной утечке управляемой памяти Коплик А.В. 545а 12 Поиск места утечки памяти Количество приватных байтов возрастает, в то время как байты в кучах остаются практически неизменными. Здесь также видно, что Байты во всех кучах также возрастают. Это говорит о возможной утечке управляемой памяти Далее мы применяем монитор ресурсов и отладчик, для того чтобы засечь, в каком из методов происходит утечка В момент выполнения определенного метода будет заметно возрастание количества потребляемой памяти Коплик А.В. 545а 13 Причина и решение проблемы Создаётся объект класса из внешней Java библиотеки для генерации PDF из XML Экземпляры классов этой библиотеки создаются каждый раз при генерации нового файла Garbage Collector не в состоянии очистить неуправляемую память даже при помощи GC.Collect() или обнулении ссылок на классы Java библиотеки Паттерн Dispose также не помогает, так как ни один из классов библиотеки не имеет Dispose() или Finalize() методов Коплик А.В. 545а 14 Причина и решение проблемы(2) class SingleTransformer { private static Transformer _instance; // Lock synchronization object private static object syncLock = new object(); // Constructor is 'protected' protected SingleTransformer() { } public static Transformer Instance(StreamSource s) { // Uses lazy initialization. if (_instance == null) { lock (syncLock) { if (_instance == null) { _instance = TransformerFactory.newInstance().newTransformer(s); _instance.setErrorListener(new TransformationErrorListener()); } } } return _instance; } } Коплик А.В. 545а Решение проблемы было заключалось в использовании паттерна Singleton. Объект, который использует неуправляемую память создаётся один раз, а затем используется всеми клиентами Таким образом исключается постепенное съедание памяти try { inputXmlStream = new ByteArrayInputStream(Encoding.UTF8.GetBytes(sXmlToTransform)); reader = new InputStreamReader(inputXmlStream, Encoding.UTF8.BodyName); for (int i = 0; i < 1500; i++) { transformer = SingleTransformer.Instance(this.streamSourceXslt); } transformer.transform ( new StreamSource(reader), new SAXResult(fop.getDefaultHandler()) ); } 15 Сравнение результатов до и после: Коплик А.В. 545а 16 Выводы: Хотя .NET и снижает количество ситуаций, когда необходимо следить за памятью, мы все равно должны уделять внимание потреблению памяти приложением Только то, что приложение работает на управляемом коде ещё не даёт нам право выкинуть лучшие практики разработки и использования ресурсов в окно и ждать чуда от Garbage Collector Нужно следить за памятью до, во время и после тестирования, разработки. Потому что только хорошо и эффективно работающие приложения способны полностью удовлетворить заказчика и уменьшить головную боль по сопровождению таких приложений. Коплик А.В. 545а 17 Спасибо за внимание! Вопросы. anatolykoplyk@gmail.com