Простое понимание механизма сборки мусора JavaScript

внешний интерфейс алгоритм JavaScript V8

Примечание:Эта статья в основном рассчитана на читателей,новичков в GC.Понимание GC у автора относительно невежественное,и желание учиться есть,но ведь времени слишком мало.Для достижения общего понимания, Я пишу заметки, чтобы понять это. В тексте много неуместных слов, поправьте меня.

предисловие

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

Неправильное использование замыканий вызовет утечку памяти в IE (до IE9).

уххх, почему это произошло до IE9? Я начал искать ответ и нашел вполне удовлетворительный:

Алгоритм сборки мусора, используемый движком JavaScript IE9, выглядит следующим образом:подсчет ссылок, для циклических ссылок приведет к тому, что сборщик мусора не сможет восстановить «должно быть освобождена» память. Вызывает бессмысленное использование памяти, то есть утечки памяти.

Сначала изучим:Утечка памяти (Memory Leak) относится к тому факту, что динамически выделенная куча памяти в программе не освобождается или не может быть освобождена по какой-либо причине, что приводит к пустой трате системной памяти, что приводит к серьезным последствиям, таким как замедление скорости работы программы или даже сбой системы.

Итак, у меня есть следующие вопросы:

  • Что такое циклическая ссылка?
  • Что такое ГК? Как это работает?
  • Почему алгоритм подсчета ссылок приводит к тому, что память не освобождается?
  • Сколько алгоритмов сборки мусора существует в JavaScript (или движках JavaScript)?

Поэтому я зашел в несуществующий гугл поискать "JS механизм сборки мусора" в "Научном Интернете", но по результатам первых 5 статей сразу видно, что они вставлены и скопированы из чужих блогов, и они все упоминают такой абзац разговора:

Когда переменная входит в среду выполнения, добавляется метка входа Когда переменная выходит, добавляется метка выхода Очистка метки означает, что сборщик мусора пометит все переменные во время выполнения, а затем удалит те, которые все еще находятся в среде или Переменная, на которую ссылается переменная в , очищает все оставшиеся переменные, которые все еще отмечены.

Извините, мое понимание ограничено, я не понимаю, что такое «оставить метку», когда удаляется «затем удалить» и как это запускается или запускается автоматически. Для этого я могу только:

Итак, я должен прочитать книгу сам и найти лучшую электронную книгу в сообществе Тьюринга.«Алгоритмы и реализации сборки мусора», После прочтения части у меня есть базовое понимание GC (по крайней мере, я знаю, как это работает).

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

что такое ГК

GC — это аббревиатура от Garbage Collection, что означает сборка мусора. Ухх, когда дело доходит до сборки мусора, я думаю о следующем сценарии:

правильно! Вот и все. В реальной жизни мы будем генерировать много мусора. Всегда есть группа людей, которые тихо собирают мусор, когда мы еще спим или выходим на работу. Так же и с программами. В процессе программная работа, Всегда будет много "мусора", которыйПространство памяти, которое программа не использует (может использоваться ранее и не будет использоваться снова). Тогда за сбор мусора отвечает GC, т.к. он работает вВнутри движка JavaScript, так что для нас, фронтенд-разработчиков, GC работает молча «до определенной степени» (обратите внимание на кавычки здесь).

Затем мы делаем это ясноGC做什么в настоящее время:

  • Найти мусор в памяти.
  • Мусор собирается, чтобы программисты могли повторно использовать эту часть пространства.

Здесь следует отметить, что, не все языки в мире естьGC, Условно говоря, языки высокого уровня вообще имеют GC, напримерJava,JavaScript,Python, В мире без GC программисты должны вручную управлять памятью, например, в языке C.malloc/free, по фактуmemory allocationаббревиатура от. Конечно, есть и C++.new/delete.

Другой момент заключается в том, что GC — древняя, но вневременная технология.Алгоритм GC был впервые выпущен в 1960 году, но сегодня нам все еще нужно изучать лучшие алгоритмы GC, чтобы делать программы «лучше».

Зачем использовать ГК

Одним словом: «Легко».

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

Зачем изучать ГК

Одним предложением: «Для того, чтобы лучше находить баги».

Мне, как фронтенд-разработчику, на самом деле не хватает знаний о компьютерных системах (возьмите себя в качестве примера), таких как операционные системы, принципы построения компьютеров и компьютерные сети. Тем не менее, эти знания действительно являются основой для решения практических задач разработки, поэтому наличие лучшей основы может привести к более быстрой разработке/эффективности обслуживания, а изучение GC может дать нам некоторые идеи о знании компьютерных систем. Например, «метод маркировки-развертки» заменяется страницей операционной системы.алгоритм второго шансаАналогично, поэтому знания интегрированы, здесь мы в контакте, тогда, когда нам нужно будет получить больше знаний в будущем, мы будем более кстати.

Основные основные понятия

  • Куча (HEAP) используется для динамического хранения对象памятии对象В JavaScript это引用类型, я говорил об этом в моем другом блоге раньшеТипы JavaScript.

  • mutator, значение этого слова неясно, оно представляет собой само приложение в GC, мы временно понимаем его какmutatorТребует много памяти.

  • allocator,mutatorОтправьте заявку, которая требует памяти здесь,allocatorОтвечает за получение достаточного объема памяти из кучи дляmutatorиспользовать.

Картинка для понимания:

  • Активный объект/неактивный объект: представляет проходmutatorСсылочный объект, например:
var a = {name: 'bar'} // '这个对象'被a引用,是活动对象。


a=null; // ‘这个对象’没有被a引用了,这个对象是非活动对象。

Несколько часто используемых алгоритмов GC

подсчет ссылок

(Картинка из "Алгоритм и реализация сборки мусора")

Как следует из названия, пусть все объекты понимают, сколько «программ» ссылаются на себя, и пусть каждый объект знает свой «индекс популярности». Возьмем простой пример:

var a = new Object(); // 此时'这个对象'的引用计数为1(a在引用)
var b = a; // ‘这个对象’的引用计数是2(a,b)
a = null; // reference_count = 1
b = null; // reference_count = 0 
// 下一步 GC来回收‘这个对象’了

Этот метод имеет преимущества и недостатки:

Преимущество

  1. Мусор можно перерабатывать мгновенно, когда указанное значение равно 0, объект немедленно подключится к свободному списку как свободное пространство, то есть. Он сразу же перерабатывается, когда становится мусором.
  2. Поскольку это мгновенная коллекция, «программа» не будет делать паузу для использования только GC в течение длительного времени, поэтому максимальное время паузы очень короткое.
  3. Нет необходимости обходить все активные и неактивные объекты в куче

недостаток

  1. Счетчик должен занимать много места, потому что верхний предел ссылки не может быть оценен.Например, могут быть 32-битные объекты, которые являются 2 в 32-й степени, ссылаясь на объект одновременно, тогда счетчику нужны 32 бита.
  2. Самый большой недостаток заключается в том, что он не может решить проблему, связанную с невозможностью повторного использования циклических ссылок.Это проблема, которая возникла до IE9 в предыдущей статье.

Простой пример:

function f(){
  var o = {};
  var o2 = {};
  o.a = o2; // o 引用 o2,o2的引用次数是1
  o2.a = o; // o2 引用 o,o的引用此时是1

  return "azerty";
}

f();

После выполнения fn пространство памяти в области действия fn должно быть освобождено, но посколькуoВнутри есть ссылка на свойствоo2, Привести кo2Счетчик цитирований всегда равен 1,o2тоже, но не специально闭包использовать, поэтому здесь следует использоватьoиo2уничтожен.

потому что алгоритм такой引用次数为0Объекты уничтожаются, и ни один из них здесь не равен 0, чтобы GC их не перерабатывал, то это内存泄漏проблема.

Этот алгоритм был постепенно заменен алгоритмом «отметка-очистка».В двигателе V8 наиболее часто используется标记-清除算法

Алгоритм развертки пометки

Процесс сборки мусора GC в основном делится на два этапа.

  • Этап маркировки: Отметьте все активные объекты.
  • Фаза очистки: Уничтожайте непомеченные (то есть неактивные объекты).

стадия маркировки

кореньЭто можно понимать как нашу глобальную область видимости, GC проходит от переменных в глобальной области видимости по области видимости слой за слоем (да, это глубокий обход), когда объект в куче проходится, это означает, что на объект ссылаются , затем он помечен маркером A, продолжайте рекурсивно перемещаться (поскольку в куче должны быть объекты, ссылающиеся на другой объект в куче), пока не будет пройден последний узел (самый глубокий уровень области видимости).

После маркировки это выглядит так:

этап очистки

Еще один обход, на этот раз обход всей кучи,Повторное использование непомеченных объектов.

Здесь мы не будем подробно обсуждать, как перераспределить полученное пространство памяти, это место немного похоже на управление дисками или управление памятью, напримерbest-fit,First-fit,Worst-fit. а также碎片化问题的产生和解决方法。

Этот метод может решить проблему циклической ссылки, поскольку два объекта не могут быть получены из глобального объекта. Поэтому их нельзя пометить и они будут собраны сборщиком мусора. Как показано на рисунке:

Преимущество:

  • Реализация проста: маркировка — это две возможности: маркировка или нет, поэтому может быть представлен только один двоичный бит.
  • Исправлена ​​проблема с круговой ссылкой

недостаток

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

Этот метод GC является запланированной задачей, то есть когда программа работает в течение определенного периода времени, унифицированный GC, как показано на рисунке:

алгоритм репликации

Алгоритм копирования очень прост для понимания с этой картинкой, то есть только активные объекты пространства копируются в другие пространства.

Разделите пространство памяти на две части, одна из которых является пространством «Откуда», а другая — пространством «Кому». и пространство To в этот момент.Измените, тогда сборка мусора завершена.

как показано на рисунке:

и

Существует также несколько алгоритмов GC, и я собираюсь обобщить алгоритмы GC (копирование, маркировка-развертка, сжатие), реализованные в V8, в графическом виде в следующем блоге.

Суммировать

Просмотрите наши предыдущие вопросы

  • Что такое циклическая ссылка?
  • Что такое ГК? Как это работает?
  • Почему алгоритм подсчета ссылок приводит к тому, что память не освобождается?
  • Сколько алгоритмов сборки мусора существует в JavaScript (или движках JavaScript)?

Подумайте об этом, должны ли мы все иметь более четкий ответ?