Обнаружение и устранение утечек памяти на платформе .NET

advertisement
Национальный Аэрокосмический Университет
им. Н.Е. Жуковского
„Харьковский авиационный институт”
Кафедра Компьютерных Систем и Сетей
Обнаружение и устранение
утечек памяти на платформе .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
Download