MiddleПроизводительностьРедкоЕщё не отвечали
Как низколатентный сборщик ZGC держит stop-the-world (STW) паузы менее миллисекунды?
ZGC выполняет маркировку, перемещение объектов и переадресацию ссылок конкурентно с работающим приложением. Цветные указатели хранят состояние GC в незанятых битах адреса, а load barrier на каждом чтении ссылки лениво переадресует устаревший указатель. Stop-the-world остаются лишь короткие сканы корней, поэтому пауза зависит от размера корневого набора, а не от размера кучи.
- ✗Считать, что
ZGC— это простоG1с бо́льшим числом потоков GC, а не конкурентный сборщик - ✗Полагать, что пауза
ZGCрастёт с размером кучи, как у старых сборщиков - ✗Путать load barrier на чтении с write barrier или считать, что барьера нет вовсе
- →Какая работа у
ZGCвсё же остаётся внутри stop-the-world паузы? - →Почему
ZGCжертвует частью пропускной способности ради субмиллисекундных пауз?
Почему паузы не растут с кучей
Классический сборщик останавливает приложение на время, пропорциональное объёму работы: чем больше живых объектов, тем дольше пауза. ZGC вынимает эту работу из паузы целиком.
- Маркировка и перемещение — конкурентные. Они идут на фоновых потоках, пока приложение работает.
- Цветные указатели. 64-битный адрес использует не все биты;
ZGCкладёт в свободные биты метки состояния объекта (marked, remapped). Метаданные GC не требуют отдельного слова в заголовке. - Load barrier. При каждом чтении ссылки исполняется короткий барьер: если по цветным битам видно, что объект переехал, ссылка чинится прямо в момент чтения — лениво, по одной. Приложение никогда не видит устаревший адрес.
- В паузе остаются только корни. Стеки потоков и глобальные корни надо просканировать синхронно. Их количество зависит от числа потоков, а не от размера кучи, — отсюда субмиллисекундная пауза даже на терабайтной куче.
Цена — пропускная способность: барьер на каждом чтении ссылки и фоновые потоки GC отбирают такты у приложения.