Комбинация графики и текста, принцип сборки мусора народного Go

Go

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

Сначала мы поговорим о том, что такое GC и какова функция GC, а затем объясним принцип GC в Go на языке, понятном каждому.

Примечание: Без моего разрешения перепечатывать эту статью без разрешения запрещено.

Что такое ГК?

В современных языках программирования высокого уровня существует два способа управления памятью: автоматический и ручной. Такие языки программирования, как C и C++, используют ручное управление памятью. Инженерам необходимо активно запрашивать или освобождать память в процессе написания кода; PHP , Java и Go и т. д. Язык использует автоматическую систему управления памятью с распределителем памяти и сборщиком мусора для выделения и освобождения памяти от его имени.Сборщик мусора — это то, что мы часто называем GC.

Что перерабатывает GC?

В приложении используются два вида памяти, а именно куча (Heap) и стек (Stack). GC отвечает за освобождение памяти кучи, а не памяти в стеке. Так почему это?

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

Типы алгоритмов GC

Существует две основные категории основных алгоритмов сборки мусора, а именно алгоритмы отслеживания сборки мусора и методы подсчета ссылок. Метод трехцветной маркировки, используемый в настоящее время в языке Go, является своего рода алгоритмом отслеживания сборки мусора.

Основная идея алгоритма отслеживания заключается в том, чтобы определить, достижим ли объект.Как только объект недоступен, он может быть собран сборщиком мусора в цикле управления сборкой мусора. Итак, как мы судим, достижим ли объект? Очень просто, первый шаг — найти все глобальные переменные и переменные в текущем стеке функций и пометить их как достижимые. Второй шаг, начиная с уже отмеченных данных, дополнительно помечает переменные, к которым они могут получить доступ, и так далее.

Алгоритм сборки мусора Go

Сборщик мусора Go развивался с момента его создания и использовался до версии v1.5 метода трехцветной маркировки в качестве алгоритма сборки мусора.Mark-And-Sweep(снятие метки) алгоритм. Начиная с версии v1.5, Go реализуетПараллельность очистки трехцветной меткиСборщик мусора, значительно уменьшающий задержку сборки мусора с сотен мс до менее 10 мс. Используется снова в v1.8смешанный барьер записиСократите время сборки мусора до менее 0,5 мс.

Недостатки алгоритмов Mark Sweep

Mark-And-Sweep, этот алгоритм реализован строго по идее следящего алгоритма. Поток выполнения этого алгоритма сборки мусора можно представить на следующей диаграмме.

垃圾回收--标记清除

Этот алгоритм в основном состоит из двух шагов:

  • Приостановите выполнение приложения и отметьте доступные объекты из корневого объекта.
  • Неотмеченные объекты очищаются, возобновляя выполнение приложения.

Самая большая проблема с этим алгоритмом заключается в том, что вся программа должна быть полностью приостановлена ​​во время выполнения GC, а сборка мусора не может выполняться асинхронно. неприемлемо. Поэтому нужен алгоритм для решения проблемы, что программа долго зависает при работе GC.

метод удаления трехцветной метки

Начиная с версии v1.5, Go реализуетПараллельность очистки трехцветной меткиСборщик мусора, примите к сведениютрехцветный маркерЭтот алгоритм не уникален для сборщика мусора Go. Основная идея этого алгоритма была предложена Эдсгером В. Дейкстра, Лесли Лэмпорт, А. Дж. Мартином, К. С. Шолтеном и Э. Ф. М. Стеффенсом, впервые опубликованным в 1978 г. в статьеОперативная сборка мусора: упражнение в сотрудничествевыше. Первый принцип алгоритма удаления трехцветных меток заключается в том, что он сортирует объекты в куче на наборы в соответствии с их цветами.

Алгоритм трехцветной маркировки делит объекты в программе на три категории: белые, черные и серые:

  • белые объекты - потенциальный мусор, память которого может быть освобождена сборщиком мусора;
  • Черные объекты — живые объекты, в том числе объекты, не имеющие никаких ссылок на внешние указатели и объекты, достижимые из корневого объекта, сборщик мусора не будет проверять дочерние объекты этих объектов;
  • Серые объекты — живые объекты, так как есть внешние указатели на белые объекты, сборщик мусора просматривает дочерние объекты этих объектов;

Текст не очень понятен, для демонстрации всего процесса удаления трехцветной метки я использую следующие картинки:

Шаг 1: В начале фазы трехцветной маркировки при входе в GC все объекты белые.

Второй шаг — пройтись по всем корневым объектам в наборе корневых узлов, пометить объекты, на которые ссылается корневой объект, как серые, и поместить их из белого набора в серый набор.

Третий шаг: пройти через серый набор, поместить объект, на который ссылается серый объект из белого набора, в серый набор, а затем поместить этот серый объект в черный набор. Шаг 4: Повторяйте шаг 3, пока в серой коллекции не останется объектов. Шаг 5: Переработайте все объекты в белом наборе, и эта сборка мусора окончена.

Упомянутый здесь корневой объект в наборе корневых узлов — это объект в стеке или глобальная переменная в куче.

написать барьер

GoПеред выполнением трехцветной маркировки на этапе GC необходимо провести подготовительную работу — открыть барьер записи (Write Barrier). Так что же такое барьер записи? Мы знаем, что трехцветная запись — это алгоритм, который может выполняться одновременно. Следовательно, в стеке функций программы во время работы GC могут быть новые выделенные объекты, так как же эти объекты должны быть уведомлены GC и как они должны быть окрашены? Если вновь созданный объект по-прежнему отмечен белым цветом, может возникнуть проблема, показанная на следующем рисунке:

В процессе GC приложение создает новые объектыI, в это время, если объект был помечен как черныйFссылка на объектI, то в этом процессе выполнения GC, потому что черный объект не будет повторно сканироваться, еслиIЕсли он окрашен в белый цвет, он будет переработан, что, очевидно, не допускается.

Это когда нам нужнонаписать барьервне.написать барьерВ основном сделайте одну вещь, измените исходную логику письма, а затем раскрасьте объект, когда он будет добавлен, и закрасьте его серым цветом. Таким образом, открытие барьера записи может гарантировать, что метод трехцветной маркировки работает безопасно и правильно в условиях параллелизма. Тогда кто-нибудь спросит, когда эти объекты, помеченные барьером записи серым цветом, будут переработаны? Ответ заключается в том, что он перерабатывается в последующем процессе GC, а все существующие объекты постепенно помечаются белым цветом во время нового процесса GC.

трихроматическая инвариантность

Чтобы обеспечить правильность параллельных или инкрементных алгоритмов маркировки, нам необходимо достичь любого из следующих двух трехцветных инвариантов:

  • Сильная трихроматическая инвариантность - черные объекты не указывают на белые объекты, а только на серые или черные объекты;
  • Слабая трихроматическая инвариантность - белый объект, на который указывает черный объект, должен содержать достижимый путь от серого объекта через несколько белых объектов.

барьерная технология

Техника барьера в сборке мусора больше похожа на метод ловушки.Это фрагмент кода, который выполняется, когда пользовательская программа читает объект, создает новый объект и обновляет указатель объекта.В зависимости от типа операции мы можем разделить их на барьеры чтения (Read Barrier) и барьер записи (Write Barrier), поскольку барьеру чтения необходимо добавлять фрагменты кода в операции чтения, что оказывает большое влияние на производительность пользовательской программы, поэтому языки программирования часто используйте барьеры записи для обеспечения трехцветной инвариантности.

Гибридный барьер записи Go

существуетGoДо языка v1.7, используяDijkstraВставка барьеров записи гарантирует строгую трехцветную инвариантность, но среда выполнения не включает вставку барьеров записи для всех корневых объектов, собранных мусором. Поскольку приложения на языке Go могут содержать сотни или тысячи горутин, а корневые объекты сборки мусора обычно включают в себя глобальные переменные и объекты стека, если среде выполнения потребуется открыть барьеры записи в стеках сотен горутин, это приведет к огромным последствиям. накладные расходы, поэтому команда Go решила внедрить его, когда фаза маркировки была завершена.Приостановите программу, закрасьте все объекты стека серым цветом и повторите сканирование., в программе с большим количеством активных горутин процесс повторного сканирования занимает от 10 до 100 мс.

Язык Go в версии 1.8 сочетает в себе барьер записи для вставки Дейкстры и барьер для удаления записи Юасы, образуя гибридный барьер записи, как показано ниже.затеняет перезаписанные объекты и затеняет новые объекты, когда текущий стек не сканируется:

writePointer(slot, ptr):
    shade(*slot)
    if current stack is grey:
        shade(ptr)
    *slot = ptr

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

Полный процесс GC

Сборщик мусора Go значительно сокращает время приостановки программы (STW) после использования алгоритма трехцветной метки-очистки и смешанных барьеров записи, в основном приостанавливая приложение перед открытием барьера записи и перед снятием барьера записи.

Весь процесс сборки мусора Go можно разделить на четыре разных этапа: подготовка метки, маркировка, завершение маркировки и очистка, Работа, выполняемая на каждом этапе, выглядит следующим образом:

отметить этап подготовки

  • Приостановить программу, в это время все процессоры войдут в безопасную точку;

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

  • переключить состояние на_GCmark, включите барьер записи, поддержку программы пользователя (Mutator Assiste) и поставьте корневой объект в очередь;

  • возобновить выполнение,Процесс маркировки и вспомогательная программа пользователя начнут маркировать объекты в памяти одновременно., алгоритмом маркировки является метод удаления трехцветной маркировки, описанный выше.Барьер записи будет помечать перезаписанные указатели и новые указатели серым цветом, а все вновь созданные объекты будут помечаться непосредственно черным цветом.;

  • Начать сканирование корневых объектов, включая стеки всех горутин, глобальные объекты и структуры данных времени выполнения, которые не находятся в куче. Текущий процессор будет приостановлен во время сканирования стеков горутин;

  • Обрабатывайте объекты в серой очереди по очереди, помечая объекты черным цветом, а объекты, на которые они указывают, серым цветом;

  • Используйте алгоритм распределенного завершения для проверки оставшейся работы и перейдите к этапу завершения тега после завершения этапа маркировки;

В начале разметки сборщик по умолчанию будет вытеснять 25% производительности ЦП, а оставшиеся 75% будут выделяться на выполнение программы. Но как только сборщик решит, что уже слишком поздно для задачи маркировки, он изменит это распределение 25% производительности. В это время сборщик вытеснит дополнительный ЦП программы.Эта часть вытесненной горутины называется Mark Assist. И поскольку основная цель вытеснения ЦП заключается в том, что сборщик мусора не успевает пометить только что добавленную память, эффект вытеснения горутины, выделяющей память, будет лучше, поэтому чем быстрее горутина выделяет память, тем больше ресурсов будет выделено. упрежденный.

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

отметить стадию завершения

  • Приостановить программу, переключите состояние на_GCmarkterminationи закрыть программу пользователя вспомогательного маркера;

  • очистить кеш потоков на процессоре;

этап очистки

  • переключить состояние на_GCoffЗапустите фазу очистки, инициализируйте состояние очистки и закройте барьер записи;

  • Восстановите программу пользователя, все вновь созданные объекты будут отмечены белым цветом;

  • Все единицы управления памятью очищаются одновременно в фоновом режиме, и очистка запускается, когда горутина применяет новую единицу управления памятью;

Процесс очистки выполняется одновременно. Накладные расходы на очистку добавляются к процессу выделения памяти кучи, поэтому это время также незаметно и не связано с задержками сборки мусора.

Суммировать

Реализация сборки мусора в языке Go очень сложна, и существует множество технических концепций и принципов, которые трудно понять.Эта статья призвана четко объяснить принцип сборки мусора в Go простыми словами, понятными каждому, в сочетании с диаграммами. , чтобы читатели могли понять Может иметь представление об общем процессе сборки мусора.

Следующее суммирует принцип сборки мусора Go в одном предложении:

Самый ранний алгоритм повторного использования, используемый сборщиком мусора Go,отметка-ясноАлгоритм должен приостанавливать прикладную программу (STW) во время выполнения, что не может обеспечить производительность параллельных программ в реальном времени. Позже сборщик мусора Go перешел на алгоритм трехцветной маркировки и очистки, а технология смешанного барьера записи обеспечила трехцветную согласованность объектов в памяти, когда Go одновременно выполнял сборщик мусора (Параллелизм здесь относится к тому факту, что GC и горутины приложений могут выполняться одновременно.).

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

Это предложение немного длинное, хахаха. Получили ли вы общее представление о сборке мусора в Go после прочтения сегодняшней статьи? Можешь обобщить своими словами? Вы можете опубликовать свое собственное резюме в сообщении, а также можете поделиться статьей со своими друзьями для прочтения. Обратите внимание на публичный аккаунт «Network Management Naobi Nao», чтобы получить все технические статьи, которые я собрал о языке Go.

использованная литература

уборщик мусора

Go Garbage Collection — Трехцветная нотация