Главная » Статьи » Управление памятью в JavaScript

Управление памятью в JavaScript

От автора: изучая управление памятью, мы имеем дело в основном с двумя вещами, а именно с тем, как распределяется память и как мы можем получить к ней доступ.

Жизненный цикл памяти состоит из 3 фаз:

Распределение

Использование

Освобождение

Фаза распределения и использования обрабатывается в JavaScript. Понимание процесса управления памятью поможет вам эффективно использовать память при создании кода.

Хранилище JavaScript

Используются 2 структуры данных:

Стек (Stack ) — это распределение статической памяти. В стеке хранятся все примитивные типы данных, такие как boolean или var, а также ссылки. Размер этих типов данных рассчитывается программой во время компиляции. Стек — это структура данных, которая работает по принципу «последний пришел — первым ушел» (LIFO). При использовании этой структуры данных память занимает пространство до завершения работы программы, что делает управление памятью неэффективным.

Куча (Heap) — это распределение динамической памяти. Объекты, функции и массивы в JavaScript размещаются в куче. Размер кучи определяется во время выполнения программы (а не во время компиляции), что делает ее динамической.

Данные хранятся в куче, а ссылки на них — в стеке.

Освобождение памяти в JavaScript

Здесь мы обсудим сборщик мусора (garbage collector). В JavaScript используются такие алгоритмы:

1. Сборка мусора с подсчетом ссылок

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

Недостаток

Есть ограничение на количество циклов. Предположим, что два элемента созданы и взаимодействуют только между собой. По сути, они бесполезны и могут быть очищены. Однако алгоритм эталонного расчета определяет, что каждый элемент идентифицируется хотя бы один раз, и не очистит их.

2. Алгоритм Mark-and-Sweep

Алгоритм Mark-and-Sweep проходит через следующие 3 этапа:

Корни: Корни — это универсальные переменные, показанные в коде. В JavaScript, например, глобальная переменная, которая может действовать как корень, является «window». То же самое для Node.js называется «global». Сборщик мусора составляет полный список всех корней.

Затем алгоритм сканирует все корни и их потомки и отмечает их как активные (то есть они не являются мусором).
Наконец, сборщик мусора удаляет все немаркированные части памяти и освобождает память.

Этот алгоритм лучше, чем предыдущий, потому что «появление нулевых ссылок» приводит к тому, что такой элемент не может быть найден.

Вопреки распространенному мнению о сборщиках мусора

Сборщики мусора являются недетерминированными. Нельзя сказать когда garbage collector очистит память. Это означает, что иногда программы используют больше памяти, чем требуется. Иногда неожиданное завершение работы может наблюдаться в наиболее важных приложениях.

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

Управление памятью в JavaScript

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

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

Четыре типа распространенных утечек JavaScript:

Глобальная диверсификация

Обратные вызовы или забытые таймеры

Ссылки вне DOM

Закрытие

Предотвращение утечек памяти

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

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

Слабые места в поведении сборщиков мусора

Управление памятью в JavaScript

Сборки мусора невозможно предсказать. Часто невозможно определить, когда именно будет произведен сбор. Это означает, что иногда используется больше памяти, чем требуется системе. Иногда временное завершение работы может наблюдаться в наиболее важных приложениях. Хотя недетерминизм означает, что нельзя быть уверенным в том, что сборка будет произведена, например при создании коллекций, во многих случаях сборщик мусора использует один и тот же шаблон выполнения. Когда никакие задания не выполняются, большинство сборщиков мусора остаются в покое. Рассмотрим следующий сценарий:

1. Выполняется большое присвоение данных в коллекции.

2. Большинство из элементов (или все они) отмечены как недоступные (предположим, что мы не используем ссылки на архивы, которые нам больше не нужны).

3. Никаких других распределений не производится.

Здесь, большинство сборщиков мусора не будут чистить устаревшие данные коллекции. Хотя для сбора доступны пустые ссылки, они не требуются сборщику. Это не серьезная утечка, но она все же приводит к более высокому использованию памяти, чем обычно.

Источник: medium.com

Редакция: Команда webformyself.

Читайте нас в Telegram, VK, Яндекс.Дзен