Gc В Go: Приоритет Скорости И Простоты

Перевод Сообщение блога главный автор сборщика мусора в Go Ричард Хадсон, изобретатель многих алгоритмов GC на других языках, один из ведущих инженеров Intel (сейчас работает в Google).

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

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

Эти улучшения времени отклика привлекли большое внимание; сообщение в блоге Робина Верлангена «Миллиарды запросов в день соответствуют Go 1.5» подтверждает наши расчеты реальными результатами.

Нам особенно понравилось скриншоты графиков производственного сервера от Алана Шрива и его комментарий «Святая скидка на 85%!» Сегодня 16 гигабайт памяти стоят 100 долларов, а все процессоры многоядерные и поддерживают гиперпоточность.

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

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

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

В этом посте представлен обзор того, что мы сделали в конструкторе Go 1.5.



Подробности

Чтобы создать сборщик мусора на следующее десятилетие, мы обратились к алгоритму, написанному десятилетия назад. Новый сборщик мусора Go — это параллельный трехцветный сборщик мусора с очисткой по меткам, который впервые был предложен Дейкстрой в 1978 году .

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

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

В начале каждого цикла сборки мусора все объекты белые.

GC передает все корневые узлы (корни) графа, которыми являются объекты, непосредственно доступные программе — это глобальные переменные и переменные в стеке — и отмечает их серым цветом.

Затем ГХ выбирает серый объект, превращает его в черный, а затем сканирует его на наличие указателей и других объектов.

Если при сканировании обнаруживается указатель на белый объект, он становится серым.

Этот процесс повторяется до тех пор, пока не останется серых объектов.

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

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

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

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

Барьер записи Go помечает объекты, которые были белыми, серыми, гарантируя, что сборщик мусора в конечном итоге просканирует их.

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

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

Найти идеальный баланс между временем, необходимым для этой паузы, и всей работой GC — одна из главных задач Go 1.6. Конечно, дьявол кроется в деталях.

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

Обсуждение деталей нижнего уровня каждой из этих областей выходит за рамки этой статьи.

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

Затем разработчик может настроить GC под себя, настроив множество параметров.

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

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

Значение по умолчанию «100» означает, что общий размер кучи теперь на 100 % больше (то есть в два раза) размера объектов, фактически достижимых после последнего цикла сборки мусора.

«200» означает, что общий размер кучи на 200% больше (то есть в три раза), чем размер фактически используемых объектов.

Если вы хотите сократить общее время сборки мусора, увеличьте GOGC. Если вы хотите уделять больше времени GC и выиграть память, уменьшите GOGC. Важно понимать, что по мере того, как объем памяти удваивается со следующим поколением оборудования, простое удвоение GOGC сократит вдвое количество циклов GC. С другой стороны, поскольку GOGC оперирует концепцией достижимых объектов, увеличение нагрузки и сопутствующее увеличение количества достижимых объектов не требуют перенастройки.

Приложение просто масштабируется.

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



Заключение

Сборка мусора в Go 1.5 переносит нас в будущее, где паузы, останавливающие мир, больше не являются препятствием для безопасного и надежного языка.

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

Это хорошее место для следующего десятилетия и того, что последует за ним.

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

Презентация Go GC: решение проблем с задержкой или слайды отчета .

Теги: #Go #gc #gc #сборщик мусора #программирование #Go

Вместе с данным постом часто просматривают: