предисловие
Эта статья является седьмой в серии подробностей о движке V8. Основное внимание уделяется механизму сборки мусора V8 и стратегии оптимизации V8 для сборки мусора. В этой статье сначала необходимо иметь предварительное представление о структуре памяти. Если вы этого не понимаете , вы можете взглянутьПодробное объяснение двигателя V8 (6) - структура памяти. В конце статьи будут ссылки на завершенный цикл статей.Этот цикл статей еще пополняется.Просим продолжать обращать внимание.
вывоз мусора
Давайте кратко разберемся с концепцией сборки мусора.Например, когда движок V8 встречает функцию в процессе выполнения кода, мы создадим контекст выполнения функции и добавим его встек вызововВверху область действия функции содержит всю переменную информацию в функции.В процессе выполнения мы выделяем память для создания этих переменных.При выполнении функции область действия функции будет уничтожена, а переменные, содержащиеся в этой также будет потеряна область действия, то процесс их уничтожения для освобождения памяти называется сборкой мусора.
Процесс сборки мусора автоматически выполняется для нас движком v8.В большинстве случаев v8 может завершить этот процесс хорошо, но как программа, она может помочь нам покрыть ситуацию ограничена, поэтому один раз нашего кода недостаточно. , это приведет к утечкам памяти.
Все мы знаем, что особенностью языка javascript является однопоточность.Однопоточность означает, что исполняемый код выполняется последовательно и может одновременно обрабатывать только одну задачу.Затем, когда V8 выполняет задачу по сбору мусора, будут выполняться другие задачи. .В состоянии ожидания другие задачи не могут быть выполнены до тех пор, пока не завершится задача по сбору мусора.Если время выполнения задачи по сбору мусора слишком велико, это неизбежно повлияет на работу пользователя.V8 также провел ряд оптимизаций для уменьшения Давайте посмотрим, как V8 выполняет сборку мусора и как она оптимизируется.
уборщик мусора
Поколенческая гипотеза — важный термин в области сбора мусора.
Стратегия сборки мусора V8 также основана на этой гипотезе.
Межпоколенческая гипотеза также очень проста и имеет две основные характеристики:
- Большинство объектов существуют в памяти в течение короткого промежутка времени, проще говоря, многие объекты становятся недоступными после выделения памяти.
- Бессмертные объекты будут жить дольше.
На основании этой гипотезыV8Куча разделена на две области: новое поколение и старое поколение, и проектируются одновременно два сборщика мусора:
- Вторичный сборщик мусораОтветственный за вывоз мусора района нового поколения
- главный сборщик мусораОтветственный за вывоз мусора в районе старого поколения
(Новое поколение и старое поколение были представлены в предыдущей статье автора, если вы не понимаете, вы можете прочитать предыдущую статью)
Вторичный сборщик мусора (Scavenging)
Вице-сборщик мусора в основном используется для восстановления нового поколения мусора, обычно наши вновь созданные объекты сначала выделяются в область памяти нового поколения.
Область памяти нового поколения будет разделена на две части (пространство).from spaceа такжеto space, две области по существу одинаковы и имеют два состояниярабочее состояниеа такжесостояние бездействияИ когда один работает, другой должен простаивать.
Например, мы создаем новый объект:
- Он будет выделен новому поколению в куче памяти, если новое поколение в новом поколенииfrom spcaeрабочее состояние, то объект будет присвоенfrom spaceсередина.
- Через некоторое время программа запускается,from spaceпамяти достигает предела хранения.
- В это время двигатель V8 выполняет операцию очистки от мусора, котораяfrom spaceОбъекты, которые больше не используются (объекты, которые не могут быть пройдены корневым узлом), помечаются.
- скопирует непомеченный объект в состояние ожиданияto spaceи переставить их по порядку, а затемfrom spaceвыполнить операцию опорожнения, и в то же времяfrom spaceпомечен как неактивный будетto spaceотмечен как рабочий.
Вышеупомянутый так называемый процесс замены, который также можно назвать процессом перелистывания, Поскольку эта операция копирования требует времени и затрат, пространство нового поколения часто невелико, поэтому оно выполняется чаще.
По мере выполнения программы некоторые объекты использовались и будут по-прежнему находиться в резерве в области нового поколения.Чтобы решить эту проблему, V8 принимаетМеханизмы продвиженияОбъекты, соответствующие условиям, сохраняются в области памяти старого поколения, а место в области памяти нового поколения освобождается.
Условия механизма продвижения:
- Объект, подвергшийся алгоритму очистки один раз и не отмеченный и не очищенный, то есть объект, подвергшийся операции флип-перестановки.
- При флип-смещении копируемый объект больше, чемto space25% площади. (from spaceа такжеto spaceдолжны быть одного размера)
Продвинутые объекты размещаются в области памяти старого поколения, которая управляется областью памяти старого поколения.
Главный сборщик мусора (Mark-Sweep и Mark-Compact)
Основной сборщик мусора в основном используется для переработки мусора старого поколения.Обычно объекты, продвигаемые в молодом поколении, и объекты с большим начальным размером будут храниться в области памяти старого поколения.
Метод, используемый первичным сборщиком мусора, полностью отличается от метода вторичного сборщика мусора.Первичный сборщик мусора сначала будет использовать алгоритм пометки-очистка (Mark-Sweep) для сборки мусора.
Процитируем описание г-на Ли Бина:
Первый этап процесса маркировки. Фаза маркировки начинается с набора корневых элементов и рекурсивно обходит набор корневых элементов.Во время этого процесса обхода элементы, которые могут быть достигнуты, называются активными объектами, а элементы, которые не достигнуты, могут рассматриваться как данные мусора.
(Источник изображения:time.geekgang.org/column/arity…)Далее идет процесс удаления мусора. Он полностью отличается от процесса удаления мусора вторичным сборщиком мусора.Основной сборщик мусора будет непосредственно очищать данные, помеченные как мусор.
Весь процесс Mark-Sweep эквивалентен процессу очистки красной части изображения выше.
Однако, когда мы очищаем память таким способом маркировки и очистки, это будет генерировать большое количество прерывистых фрагментов памяти.Когда мы хотим сохранить большой объект, может не хватить места, поэтому в дополнение к выполнениюМарк-разверткаПомимо алгоритма, также черезМарк-КомпактАлгоритм выполняет сборку мусора.
Марк-КомпактАлгоритм в основном делится на два шага:
- Во-первых, это тот же процесс маркировки.
- Переместите неотмеченные объекты (живые объекты) влево и очистите память за пределами границ после завершения перемещения.
V8 проходитМарк-разверткатак же какМарк-КомпактДва алгоритма выполняют сборку мусора в области памяти старого поколения, что является основной задачей главного сборщика мусора.
Стратегия оптимизации сбора мусора (Ориноко)
Методы, используемые описанными выше двумя сборщиками мусора V8, на самом деле очень распространены в языках программирования с механизмами сборки мусора.
Важный критерий оценки качества работы механизма сборки мусора зависит от времени приостановки основного потока при выполнении сборки мусора.Чтобы оптимизировать эту часть опыта (уменьшить время приостановки основного потока), запускается V8. сборщик мусора под кодовым названием Orinoco Project специально оптимизировал стратегию сбора мусора.
Orinoco реализует в общей сложности три оптимизации
- Параллельная сборка мусора (параллельно)
- Инкрементная сборка мусора (инкрементальная)
- Параллельная сборка мусора (concurrent)
Параллельная сборка мусора
Поговорим о первой оптимизацииПараллельная сборка мусора, мы упоминали ранееЗона памяти молодого поколенияа такжеобласть памяти старого поколенияСогласно сборке мусора, прежде чем говорилось, мы можем определить область памяти в новом генерировании, а область памяти объекта старого поколения объекта полностью отличается, то это реализация нового поколенияОтметить -> Копировать -> Очиститьоперации и исполнение старого поколенияпометить -> очистить -> компактноОперация без каких-либо зависимостей.
Поэтому Orinoco считает, что логика очистки мусора без зависимостей (более одной из вышеперечисленных) оптимизирована за счет параллельного выполнения, чтобы сократить время, затрачиваемое основным процессом на выполнение сборки мусора. Поэтому Orinoco достаточно запустить несколько вспомогательных процессов для завершения работы по очистке мусора одновременно, как показано ниже:
(Источник изображения:V8.Dev/блог/корзина-…)
Инкрементальная сборка мусора
Вторая оптимизацияИнкрементальная сборка мусора, несмотря на то чтоПараллельная сборка мусораПараллельный механизм может эффективно уменьшить занятость основного процесса, но для выполнения метки за один раз перед лицом большого объекта потребуется много времени.С 2011 года в V8 введен механизм инкрементной метки,Механизм инкрементной сборки мусора.
(Источник изображения:V8.Dev/блог/корзина-…)Разбивка большой задачи на более мелкие фрагменты позволяет запускать приложения между фрагментами.
Эта оптимизация создает большую проблему для реализации маркеров: как сохранить результаты сканирования в это время? Если отмеченные данные модифицируются основным потоком, как с этим правильно поступить?
Так что V8 используетсяФлага такжеОтметьте рабочий листреализовать разметку.
Биты маркера используются для обозначения трех цветов:белый(00),серый (10),черный(11),
- В начальном состоянии все объектыбелыйТо есть объекты, на которые не ссылается корневой узел.
- Когда сборщик мусора находит объект, на который ссылаются, он помечает этот объект каксерыйи вставьте его вОтметьте рабочий листсередина.
- Отметьте рабочий листполучат доступ ко всем существующимсерыйобъекта и получить доступ ко всем подобъектам объекта, пометив объект какчернить.
- Отметьте рабочий листбудет продолжать вводитьсясерый(каждый раз, когда будет найден новый помечаемый объект, он будет вставлен вотметить в рабочем листе)
- еслиОтметьте рабочий листбольше не надосерыйобъект, то он представляет, что все объектычернитьилибелый, то вы можете с уверенностью очистить егобелыйОбъект.
Весь процесс показан на рисунке:
Отметить от корневого узла
Обработка обхода
окончательный вид после завершения
Это процесс немного извилистый, тогда приведу пример (не знаю уместно или нет)
Как банда воров
- Полиция поймала банду воровA(отмечено серым), но у полиции нет другого способа осудить его, кроме как в суд (отметьте в рабочем листе).
- в судеAдоверенные члены бандыB, полиция будетBПойман обратно (отмечено серым) в суд (отмечено на рабочем листе).
- BСказал, что есть еще одна бандаC,ноCНи одно преступление не может быть нарушено (отмечено белым по умолчанию).
- В этот момент дело будетBОсуждение (отмечено черным) затем будетAосуждение (отмечено черным), затемA BПриговор.
Итак, вернемся к предыдущему вопросу, если помеченные данные изменяются основным потоком, как с этим правильно поступить? V8 используетбарьер записиЭтот механизм нетрудно понять, короче говоря, он заключается в том, чтобы заставить черный объект не указывать прямо на белый объект. Например, мы выполняем операцию записи:
// 调用 `object.field = value` 之后
write_barrier(object, field_offset, value) {
if (color(object) == black && color(value) == white) {
set_color(value, grey);
marking_worklist.push(value);
}
}
Измените только что написанный объект непосредственно с исходного белого на серый, затемОтметьте рабочий листЕсли пустого места нет, продолжайте процесс маркировки, чтобы убедиться в правильности данных маркировки.
одновременная сборка мусора
Параллельная сборка мусора и параллельная сборка мусора совершенно разные, представленные графом
Параллельная сборка мусора происходит в основном потоке и рабочих потоках. Приложение приостанавливается на протяжении фазы параллельной маркировки.
Параллельная сборка мусора происходит в основном в рабочих потоках. Приложение может продолжать работать, пока выполняется параллельная сборка мусора.
Обычно вышеперечисленные три метода не существуют по отдельности, а используются вместе следующим образом:
Сбор мусора при простое
Сбор мусора при простое не является частью проекта Orinoco и является стратегией оптимизации, реализованной V8.
Часто планировщик использует информацию о занятости очереди задач и сигналы, полученные от других компонентов V8, чтобы позволить ему оценить, когда V8 простаивает и как долго он может оставаться бездействующим. Используя эту информацию, V8 может выделить некоторые низкоприоритетные задачи по сборке мусора для выполнения в это время простоя.
Например, V8 будет использовать браузер Chrome.task scheduler, динамически перераспределяет приоритеты задач на основе сигналов, полученных от различных других компонентов Chrome, и различных эвристик, предназначенных для оценки намерений пользователя. Например, если пользователь касается экрана, планировщик отдает приоритет отрисовке экрана и задачам ввода на период 100 миллисекунд, чтобы гарантировать, что пользовательский интерфейс остается отзывчивым, когда пользователь взаимодействует с веб-страницей.
Например, при рендеринге со скоростью 60 кадров в секунду межкадровый интервал составляет 16,6 мс. Если на экране нет действительных обновлений, тоtask schedulerИнициируется более длительный период простоя, который длится до тех пор, пока не будет инициирована следующая ожидающая задача, ограниченный 50 мс, чтобы Chrome оставался чувствительным к неожиданным действиям пользователя.
Более подробное описание простаивающих задач можно найти наqueue.ACM.org/detail Кухонные двери?…Эта статья, эта статья не вдается в подробности.
Суммировать
В этой статье в основном рассматривается механизм сборки мусора V8 и некоторые используемые методы оптимизации.Механизм сборки мусора относительно прост, но метод оптимизации Orinoco относительно сложен для понимания (автор не полностью понял, как выполняется параллельная сборка мусора, поэтому не является подробным Если у вас есть какие-либо ошибки, пожалуйста, обсудите с автором в комментариях.Если вы считаете, что эта статья полезна для вас, пожалуйста, поставьте большой палец вверх, большое спасибо.
Справочная статья
queue.ACM.org/detail Кухонные двери?…
time.geekgang.org/column/arity…
V8.Dev/blog/concur…
V8. То есть можно только /blog/Oday OC…
серия статей
Подробное описание двигателя V8 (1) — обзор
Подробное объяснение двигателя V8 (2) - AST
Подробное объяснение двигателя V8 (3) — эволюция V8 с точки зрения байт-кода
Подробное объяснение движка V8 (4) - как выполняется байт-код
Подробное объяснение двигателя V8 (5) - встроенный кэш
Подробное объяснение двигателя V8 (6) - структура памяти
Подробное объяснение двигателя V8 (7) — механизм сбора мусора
Подробное объяснение движка V8 (8) - очередь сообщений
Подробное объяснение двигателя V8 (9) - функция сопрограммы и генератора