Утечки памяти мешают пользователям долго работать с вашим веб-приложением – из-за них можно потерять аудиторию. Попробуем разобраться как этого издежать.
Перевод публикуется с сокращениями, автор оригинальной статьи Rafal Kuć.
Важно знать, как пользователи взаимодействуют с вашим софтом – это имеет решающее значение для обеспечения наилучшего UX. Основными показателями являются следующие: время загрузки страницы, скорость обработки HTTP-запросов и время до первого байта. Однако сами метрики – это лишь часть общей картины.
Вы должны быть уверены, что знаете обо всех пользовательских проблемах, как только они появляются в продакшене, а в идеале, до него. Одной из таких бед являются утечки памяти.
Когда это происходит, приложение постепенно замедляется и в какой-то момент работать с ним становится невозможно. В некоторых случаях это может замедлить работу веб-браузера и компьютера. Такие проблемы трудно отслеживать и отлаживать, поскольку они сразу не видны и проявляются только при длительной работе.
Для отслеживания этих неприятностей можно использовать Sematext Experience – инструмент мониторинга, позволяющий не только контролировать использование веб-приложениями памяти, но также быстро и эффективно обнаруживать утечки. В статье мы подробно рассмотрим, как это делается.
Утечка памяти – это избыточное потребление ресурсов из-за неправильного управления распределением памяти в программном обеспечении. Она происходит, когда веб-приложение выделяет память и продолжает использовать ее даже когда та больше не нужна.
Память освобождается, когда она больше не выделена в коде. Однако бывают ситуации, когда память продолжает быть выделенной на протяжении всего жизненного цикла приложения. Иногда это необходимо, но если мы больше не нуждаемся в информации, а область памяти все еще выделена, можно говорить об утечке.
Во фронтенд-приложениях существует несколько распространенных паттернов, которые могут вызвать утечку памяти. К ним относятся:
function(product, timestamp, page) {
visited.push({product, timestamp, page})
}
Дальнейшая идея заключается в том, чтобы хранить все в бекенде, периодически отправляя данные. Однако чтобы создать утечку, мы забываем сделать одну штуку: после отправки данных в бекенд не очищаем массив. Это означает, что на данные по-прежнему ссылаются из нашего веб-приложения. Если пользователь не закрывает вкладку, данные будут продолжать добавляться, что приведет к утечке памяти.
Теперь посмотрим, как можно идентифицировать возникновение утечки памяти с помощью 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".push(e);break; default:break}})});p.observe({entryTypes:["longtask","element"]})}e[s+"lt"]={ longTasks,timingElements:i,inPageLoad:c,observer};if(t){var u=r.createElement; u.async=1;u.src=t;var f=r.getElementsByTagName[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 помогут выполнить все необходимые для отправки метрик шаги.
Если бы у вас было подобное смоделированному веб-приложение с утечкой, вы могли бы наблюдать, как бесконечно растет потребление памяти. Не совсем бесконечно: рано или поздно работа браузера завершится аварийно. Диаграмма использования памяти должна быть привязана к некоторым значениям. Например, вот так:
Можно наблюдать скачкообразные сегменты, но в более длительном периоде использование памяти остается между максимумом и минимумом и не растет бесконечно. Мы видим, что в нашем гипотетическом примере e-commerce это не так. Если перейти к просмотру одной сессии, виден постоянный рост использования памяти с менее чем 2 МБ до 12 МБ, и нет никакого падения в течение этого времени. Обычно это означает, что где-то в приложении произошла утечка памяти. Глядя на данные сессии, мы можем видеть загрузку страниц и HTTP-запросы:
Этот экран помогает сузить круг ошибок, показывая все действия пользователя: какие вызовы API были сделаны, какие части приложения выполнялись, какие ресурсы были загружены. Остается только изучить все части кода, и после дальнейшего исследования можно будет найти проблемные фрагменты.
Дополнительные материалы:
Перевод публикуется с сокращениями, автор оригинальной статьи 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
(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 – он предоставляет вам комплексное, доступное и простое в использовании решение для мониторинга.Дополнительные материалы:
- 10 лучших инструментов облачного мониторинга: плюсы и минусы
- Мониторинг файлов вместе с Java NIO
- 12 инструментов DevOps-инженера для мониторинга архитектуры
- Как осуществить online-мониторинг нагрузки на сервере?