Как найти утечки памяти на сайтах и в веб-приложениях

Kate

Administrator
Команда форума
Утечки памяти мешают пользователям долго работать с вашим веб-приложением – из-за них можно потерять аудиторию. Попробуем разобраться как этого издежать.

Перевод публикуется с сокращениями, автор оригинальной статьи Rafal Kuć.
Важно знать, как пользователи взаимодействуют с вашим софтом – это имеет решающее значение для обеспечения наилучшего UX. Основными показателями являются следующие: время загрузки страницы, скорость обработки HTTP-запросов и время до первого байта. Однако сами метрики – это лишь часть общей картины.
Вы должны быть уверены, что знаете обо всех пользовательских проблемах, как только они появляются в продакшене, а в идеале, до него. Одной из таких бед являются утечки памяти.
Когда это происходит, приложение постепенно замедляется и в какой-то момент работать с ним становится невозможно. В некоторых случаях это может замедлить работу веб-браузера и компьютера. Такие проблемы трудно отслеживать и отлаживать, поскольку они сразу не видны и проявляются только при длительной работе.
Для отслеживания этих неприятностей можно использовать Sematext Experience – инструмент мониторинга, позволяющий не только контролировать использование веб-приложениями памяти, но также быстро и эффективно обнаруживать утечки. В статье мы подробно рассмотрим, как это делается.
7b0d22d6c36c45faac7839d3952af86a.png

Что такое утечка памяти​




Утечка памяти – это избыточное потребление ресурсов из-за неправильного управления распределением памяти в программном обеспечении. Она происходит, когда веб-приложение выделяет память и продолжает использовать ее даже когда та больше не нужна.

Что вызывает утечку памяти: признаки, на которые следует обратить внимание​

Веб-приложение будет создавать и использовать различные константы, переменные и функции для выполнения работы. Все они требуют памяти. В JavaScript и других языках программирования высокого уровня, когда ресурс больше не нужен, он будет удален автоматической системой управления памятью, называемой сборщиком мусора.
Память освобождается, когда она больше не выделена в коде. Однако бывают ситуации, когда память продолжает быть выделенной на протяжении всего жизненного цикла приложения. Иногда это необходимо, но если мы больше не нуждаемся в информации, а область памяти все еще выделена, можно говорить об утечке.
Во фронтенд-приложениях существует несколько распространенных паттернов, которые могут вызвать утечку памяти. К ним относятся:
  • Замыкания – внутренние функции, имеющие ссылки на переменные внешних. Таким образом внутренняя функция не позволяет сборщику мусора освободить память.
  • Случайные глобальные переменные – ранее необъявленные переменные станут глобальными и не будут освобождены.
  • Несвязанные коллекции – массивы, мапы и наборы позволяют хранить данные в каком-то виде, но с багами в коде они могут привести к утечке памяти из-за вечного хранения ссылок. Такой пример будет рассмотрен ниже.
  • Отсоединенный DOM – элемент Document Object Model, который больше не используется, но на него продолжают ссылаться.
  • Несвязанные таймеры – работающие вечно и сохраняющие объекты таймеры могут привести к утечке памяти.

Как обнаружить утечки памяти: пример приложения​

Чтобы проверить фактическую утечку памяти, создадим простое веб-приложение, имитирующее мониторинг поведения пользователей e-commerce. Страница отслеживает продукты, с которыми пользователи взаимодействуют при просмотре магазина. Каждое показанное объявление, возвращенный товар из поиска и т. д. – все помещается в массив. Код выглядит следующим образом:
function(product, timestamp, page) {
visited.push({product, timestamp, page})
}

Дальнейшая идея заключается в том, чтобы хранить все в бекенде, периодически отправляя данные. Однако чтобы создать утечку, мы забываем сделать одну штуку: после отправки данных в бекенд не очищаем массив. Это означает, что на данные по-прежнему ссылаются из нашего веб-приложения. Если пользователь не закрывает вкладку, данные будут продолжать добавляться, что приведет к утечке памяти.
Теперь посмотрим, как можно идентифицировать возникновение утечки памяти с помощью Sematext и его способности измерять использование памяти сайтом и приложением.

Интеграция Sematext Experience с веб-приложением​

Первый шаг – настроить приложение на использование Sematext Browser SDK для отправки данных в облако Sematext.
Для этого добавим скрипт перед закрывающим тегом </head>:
<script type="text/javascript">
(function(e,r,n,t,s){var a=[];e=function(){a.push(arguments)};e.queue=a; var o=[];var i=[];var c=true;var p=void 0;if(window.PerformanceObserver&& window.PerformanceObserver.supportedEntryTypes&&( PerformanceObserver.supportedEntryTypes.indexOf("longtask")>=0|| PerformanceObserver.supportedEntryTypes.indexOf("element")>=0)){ p=new PerformanceObserver(function(e){e.getEntries().forEach(function(e){ switch(e.entryType){case"element":i.push(e);break;case"longtask":eek:.push(e);break; default:break}})});p.observe({entryTypes:["longtask","element"]})}e[s+"lt"]={ longTasks:eek:,timingElements:i,inPageLoad:c,observer:p};if(t){var u=r.createElement(n); u.async=1;u.src=t;var f=r.getElementsByTagName(n)[0];f.parentNode.insertBefore(u,f)}})
(window,document,"script","//cdn.sematext.com/experience.js","strum");
</script>

Второй шаг зависит от типа вашего веб-приложения и используемого фреймворка – нужно сообщить Browser SDK, как ему себя настроить. Например, для стандартного развертывания нескольких веб-страниц вы бы использовали перед закрывающим тегом </head> что-то вроде этого:
<script type="text/javascript">
strum('config', { token: '<token>', 'receiverUrl': 'https://rum-receiver.sematext.com' });
</script>

Если вы используете какую-либо одностраничную архитектуру, инструкции по установке приложения Sematext Experience помогут выполнить все необходимые для отправки метрик шаги.

Выявление утечки памяти​

Зная что делает пользователь, мы можем взглянуть на графики в Sematext Experience. Перейдите к отчету об использовании памяти в приложении:
99062ac2d0c84b4a7c8374569240cc78.png

Если бы у вас было подобное смоделированному веб-приложение с утечкой, вы могли бы наблюдать, как бесконечно растет потребление памяти. Не совсем бесконечно: рано или поздно работа браузера завершится аварийно. Диаграмма использования памяти должна быть привязана к некоторым значениям. Например, вот так:
67d489e75d20ed8adda0d89000539f56.png

Можно наблюдать скачкообразные сегменты, но в более длительном периоде использование памяти остается между максимумом и минимумом и не растет бесконечно. Мы видим, что в нашем гипотетическом примере e-commerce это не так. Если перейти к просмотру одной сессии, виден постоянный рост использования памяти с менее чем 2 МБ до 12 МБ, и нет никакого падения в течение этого времени. Обычно это означает, что где-то в приложении произошла утечка памяти. Глядя на данные сессии, мы можем видеть загрузку страниц и HTTP-запросы:
21bb8ac33ac0c69413026e4eb6d91f0c.png

Этот экран помогает сузить круг ошибок, показывая все действия пользователя: какие вызовы API были сделаны, какие части приложения выполнялись, какие ресурсы были загружены. Остается только изучить все части кода, и после дальнейшего исследования можно будет найти проблемные фрагменты.

Поддерживаемые браузеры​

Возможности измерения памяти Sematext Browser SDK зависят от используемого браузером API для предоставления связанных с памятью метрик. Поддерживается он только в Chrome и проходил испытания Chrome Origin для Chrome 82-87. Начиная с Chrome 89 API будет полностью доступен — это означает, что пользователям потребуется новейший веб-браузер Google.

Заключение​

С помощью правильных инструментов выявить проблемы с утечкой памяти довольно просто. Именно для этой цели был создан и постоянно совершенствуется Sematext Experience – он предоставляет вам комплексное, доступное и простое в использовании решение для мониторинга.
Дополнительные материалы:
Источник статьи: https://proglib.io/p/kak-nayti-utechki-pamyati-na-saytah-i-v-veb-prilozheniyah-2021-03-05
 
Сверху