[Из песочницы] Проблемы поиска утечки памяти в веб-приложении с помощью Chrome DevTools
Браузер Google Chrome поставляется с превосходными инструментами для разработчика, они же есть в Яндекс.Браузере, новой Опере, и в других браузерах, основанных на базе Chromium.Среди них есть потрясающие инструменты для работы с памятью, ознакомиться с которыми можно в статье пользователя Panya — «Как находить и устранять утечки памяти на примере Яндекс.Почты».
Javascript хранит объект в памяти до тех пор, пока на него есть хоть одна ссылка. Как только вы удаляете все ссылки на объект, он уничтожается сборщиком мусора.
Таким образом, чтобы удалить объект, нужно удалить все ссылки на него.
Это кажется очень простым, но есть несколько достаточно неожиданных «мест» где могут храниться ссылки на объекты, тем самым задерживая их удаление, и создавая утечку памяти.
1. Консольный вывод.Если в процессе работы приложения в консоль выводится отладочная информация, то прежде чем замерять память, консоль стоит очистить.
Это не обязательно приведет у уменьшению потребления памяти, но на своей практике я уже встречался со случаями, когда очистка консоли освобождала объекты из памяти.
2. Включенные экспериментальные функции браузера. В моем случае это были «JavaScript frameworks debugging» и «Support asynchronous call stacks», которая уже вышла из экспериментальных.
До тех пор, пока они были включены, часть объектов в памяти не удалялось сборщиком мусора, хотя в самом приложении ссылок на них не было.
Когда я снял галочки, проблемы исчезли.
К слову, в приложении, которое я разрабатываю, рендерятся сложные шаблоны на AngularJS, и со включенными экспериментальными функциями рендер длился около 10 секунд, а с отключенными — всего 3.
Как дела обстоят с другими экспериментальными функциями, сказать не могу, но советую на время поиска утечек памяти все отключать.
3. Расширения браузера. В моем случае это был Batarang. Это инструмент для отладки приложений, построенных на AngularJS, и он у себя внутри сохраняет ссылки на scope приложения, что создавало утечку памяти.
После того, как я отключил расширение, память стала освобождаться.
Плагинов, влияющих на работу с памятью может быть множество. По ссылке, которую я дал в начале статьи, рекомендуется отключать вообще все плагины, что, как я считаю, является правильным советом.
4. Функция «Record Heap Allocations». Эта функция нужна для того, чтобы определить, в какой момент сколько памяти откладывается приложением, и что конкретно в какой момент откладывается. Это очень полезная вещь, но в работе этой функции есть некоторые особенности.
Первое — функция показывает не только сколько памяти откладывается, но и сколько освобождается («свободная» память становится светло-серой), при этом показывать может не всегда точно.
Для того, чтобы понять, в какой момент сколько памяти используется, стоит использовать Timeline.
Для теста я одно действие в приложении, повторял многократно, и смотрел, что происходит с памятью.
Record Heap Allocations показывал, что память очищалась не полностью, и после каждого действия оставалось немного занятой памяти, в то время, как Timeline показывал, что все очищается хорошо, и никаких утечек нет.
Второе — не стоит использовать Record Heap Allocations и Timeline одновременно.
Если одновременно включить Record Heap Allocations и Timeline, то Timeline будет показывать, что память течет, то есть используется во все большем и большем объеме.
Если же включить один только Timeline, то память течь не будет, что приводит к выводу, что Record Heap Allocations удерживает ссылки на объекты, а потому непригоден для отслеживания «освобождения» памяти.
Заключение В статье я привел 4 примера мест, где могут быть сохранены ссылки на объекты, препятствующие их удалению сборщиком мусора.Естественно, это не все проблемные места, а лишь только те, с которыми столкнулся лично я.
Что-то из этого, возможно, уже исправлено, а что-то, возможно, будет исправлено в будущем.
Важно понимать, что помимо самого разрабатываемого приложения ссылки могут быть сохранены и в других местах, и это следует учитывать при поиске утечек памяти.