eFusion 05 марта 2021

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

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

Перевод публикуется с сокращениями, автор оригинальной статьи Rafal Kuć.

Важно знать, как пользователи взаимодействуют с вашим софтом – это имеет решающее значение для обеспечения наилучшего UX. Основными показателями являются следующие: время загрузки страницы, скорость обработки HTTP-запросов и время до первого байта. Однако сами метрики – это лишь часть общей картины.

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

Когда это происходит, приложение постепенно замедляется и в какой-то момент работать с ним становится невозможно. В некоторых случаях это может замедлить работу веб-браузера и компьютера. Такие проблемы трудно отслеживать и отлаживать, поскольку они сразу не видны и проявляются только при длительной работе.

Для отслеживания этих неприятностей можно использовать Sematext Experience – инструмент мониторинга, позволяющий не только контролировать использование веб-приложениями памяти, но также быстро и эффективно обнаруживать утечки. В статье мы подробно рассмотрим, как это делается.

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

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

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

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

Веб-приложение будет создавать и использовать различные константы, переменные и функции для выполнения работы. Все они требуют памяти. В 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[s]=function(){a.push(arguments)};e[s].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":o.push(e);break; default:break}})});p.observe({entryTypes:["longtask","element"]})}e[s+"lt"]={ longTasks:o,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. Перейдите к отчету об использовании памяти в приложении:

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

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

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

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

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

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

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

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

Заключение

С помощью правильных инструментов выявить проблемы с утечкой памяти довольно просто. Именно для этой цели был создан и постоянно совершенствуется Sematext Experience – он предоставляет вам комплексное, доступное и простое в использовании решение для мониторинга.

Дополнительные материалы:

Источники

МЕРОПРИЯТИЯ

Комментарии

ВАКАНСИИ

Добавить вакансию
Продуктовый аналитик в поддержку
по итогам собеседования
DevOps
Санкт-Петербург, от 150000 RUB до 400000 RUB
Продуктовый аналитик
Екатеринбург, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ