вывоз мусора
Для разработчиков управление памятью JavaScript является автоматическим и невидимым. Примитивные значения, объекты, функции, которые мы создаем... все это занимает память.
Что происходит, когда нам что-то больше не нужно? Как движок JavaScript находит его и очищает?
Доступность
Основные концепции управления памятью в JavaScript:доступность.
Короче говоря, «достижимые» значения — это те, которые доступны или могут использоваться каким-либо образом. Они должны храниться в памяти.
-
Здесь указан базовый набор изначально достижимых значений, которые, очевидно, не могут быть освобождены.
Например:
- Локальные переменные и параметры текущей функции.
- При вложенности вызовов переменные и параметры всех функций в текущей цепочке вызовов.
- глобальные переменные.
- (и некоторые внутренние)
Эти значения называютсякорни.
-
Значение считается достижимым, если оно может достичь любого другого значения из корня по ссылке или цепочке ссылок.
Например, объект считается достижимым, если в локальной переменной есть объект, и этот объект имеет свойство, которое ссылается на другой объект. И контент, на который он ссылается, также доступен. Ниже приведен подробный пример.
Существует движок JavaScript, который называетсяуборщик мусоравещи выполняются в фоновом режиме. Он отслеживает состояние всех объектов и удаляет те, которые больше не доступны.
простой пример
Вот самый простой пример:
// user 具有对这个对象的引用
let user = {
name: "John"
};
Стрелка здесь описывает ссылку на объект. глобальная переменная"user"
ссылка на объект{name:"John"}
(Давайте назовем его Джоном для краткости). Джона"name"
Свойства хранят примитивное значение, поэтому оно записывается внутри объекта.
еслиuser
Значение переопределяется, и ссылка исчезает:
user = null;
Теперь Джон недоступен. Поскольку ссылки нет, к ней нельзя получить доступ. Сборщик мусора посчитает это мусорными данными и соберет их, после чего освободит память.
две цитаты
Теперь представим, что мы положилиuser
цитаты скопированы вadmin
:
// user 具有对这个对象的引用
let user = {
name: "John"
};
let admin = user;
Теперь, если вы выполните операцию прямо сейчас:
user = null;
...тогда объект все еще может быть переданadmin
Доступ к этой глобальной переменной осуществляется, поэтому объект все еще находится в памяти. Если мы перепишемadmin
, объект удаляется.
взаимосвязанные объекты
Теперь рассмотрим более сложный пример. Это семья:
function marry(man, woman) {
woman.husband = man;
man.wife = woman;
return {
father: man,
mother: woman
}
}
let family = marry({
name: "John"
}, {
name: "Ann"
});
marry
Функция «объединяет» два объекта, заставляя их ссылаться друг на друга, и возвращает новый объект, содержащий оба объекта.
Получившаяся структура памяти:
Пока все объекты доступны.
Теперь давайте удалим две ссылки:
delete family.father;
delete family.mother.husband;
Удаление только одной из этих двух ссылок недостаточно, поскольку все объекты по-прежнему доступны.
Однако, если мы удалим оба, то увидим, что ссылок на Джона больше нет:
Внешние ссылки не важны, только передача ссылок может сделать объекты доступными. Итак, Джон теперь недоступен и будет удален из памяти, и все данные Джона также станут недоступны.
После сбора мусора:
недоступные острова
Несколько объектов ссылаются друг на друга, но ни на один из их объектов нет внешних ссылок, которые также могут быть недоступны и удалены из памяти.
Исходный объект такой же, как и выше. Потом:
family = null;
Внутреннее состояние памяти станет:
Этот пример показывает важность концепции доступности.
Очевидно, Джон и Энн все еще связаны с поступающими ссылками. Однако этого недостаточно.
сказал ранее"family"
Объект больше не привязан к корню и не имеет на него внешних ссылок, поэтому он становится «островком» и будет удален из памяти.
внутренний алгоритм
Основной алгоритм сборки мусора называется «отметить и очистить».
Периодически выполняйте следующие шаги «сборки мусора»:
- Сборщик мусора находит все корни и «помечает» (запоминает) их.
- Затем он проходит и «отмечает» все ссылки с них.
- Затем он перебирает отмеченные объекты и отмечаетИхЦитировать. Все пройденные объекты запоминаются, чтобы избежать повторного обхода одного и того же объекта в будущем.
- ... и так далее, пока не будут посещены все доступные (из корня) ссылки.
- Объекты, которые не отмечены, удаляются.
Например, сделайте так, чтобы наш объект имел следующую структуру:
Справа отчетливо виден «недостижимый остров». Теперь давайте посмотрим, как с этим справится сборщик мусора «пометить и очистить».
Первым шагом помечаются все корни:
Затем их ссылки помечаются:
... если есть еще цитаты, продолжайте отмечать:
Теперь объекты, недоступные через этот процесс, считаются недоступными и будут удалены.
Мы также можем представить этот процесс как выливание гигантского ведра с краской из корня, которое проходит через все ссылки и помечает все достижимые объекты. Затем удалите немаркированные.
Это концепция того, как работает сборка мусора. Движок JavaScript сделал много оптимизаций, чтобы ускорить сборку мусора, не влияя на нормальное выполнение кода.
Некоторые предложения по оптимизации:
- Коллекция поколений- Объекты разделены на две группы: "новые" и "старые". Многие объекты появляются, заканчивают свою работу и быстро умирают, их можно быстро убрать. Объекты, которые живут долго, становятся «устаревшими» и проверяются реже.
- Инкрементная коллекция- Если объектов много и мы пытаемся перебрать и пометить сразу весь набор объектов, это может занять некоторое время и привести к заметной задержке выполнения. Так что движок пытается делать сборку мусора по частям. Затем эти части будут обрабатываться одна за другой. Это требует дополнительных маркеров между ними, чтобы отслеживать изменения, но тогда возникает множество крошечных задержек вместо одной большой задержки.
- коллекция свободного времени- Сборщик мусора будет пытаться запускаться только тогда, когда ЦП простаивает, чтобы уменьшить возможное влияние на выполнение кода.
Существуют и другие оптимизации и разновидности алгоритмов сборки мусора. Как бы я ни хотел описать их здесь, я должен остановиться, потому что разные движки имеют разные настройки и приемы. И, что более важно, все меняется по мере развития движка, поэтому не стоит изучать этот материал «заранее», когда в этом нет реальной необходимости. Если, конечно, это не отношения чистого интереса. Я предоставил вам несколько соответствующих ссылок ниже.
Суммировать
Главное, что нужно знать:
- Сбор мусора происходит автоматически, мы не можем заставить его или предотвратить.
- Когда объект доступен, он должен существовать в памяти.
- Быть ссылкой — это не то же самое, что быть доступным (от корня): набор взаимосвязанных объектов может быть недоступен в целом.
Современные движки реализуют продвинутые алгоритмы сборки мусора.
Некоторые из них описаны в книге «Справочник по сбору мусора: искусство автоматического управления памятью» (Р. Джонс и др.).
Если вы знакомы с низкоуровневым программированием, см. статью для получения более подробной информации о сборщике мусора двигателя V8.V8 Tour: Сбор мусора.
Блог V8Также время от времени публикуются статьи об изменениях в управлении памятью. Конечно, чтобы научиться сборке мусора, вам лучше всего подготовиться, изучив внутренности двигателя V8 и прочитав книгу под названиемVyacheslav EgorovБлог инженера по двигателям V8. Я говорю «V8», потому что о нем больше всего написано в сети. Для других движков многие методы аналогичны, но во многом отличаются сборкой мусора.
Хорошее понимание движка будет полезно, когда вам понадобится низкоуровневая оптимизация. После знакомства с языком программирования разумно сделать знакомство с движком в качестве следующего плана.
Эта статья была впервые опубликована в общедоступной учетной записи WeChat «Technology Talk». Добро пожаловать в WeChat, ищите и подписывайтесь, и подписывайтесь на более интересный контент.
Учебники по современному JavaScript: учебные пособия по современному JavaScript с открытым исходным кодом, от начального до продвинутого.Рекомендовано официальной документацией React, учебным пособием по JavaScript вместе с MDN..
Читайте онлайн бесплатно:zh.javascript.info
Отсканируйте приведенный ниже QR-код, подпишитесь на общедоступную учетную запись WeChat «Technology Talk» и подпишитесь на более интересный контент.