В чем отличие планировщика Go от планировщика операционной системы
Что проверяют
Знаете ли вы модель GMP и понимаете ли, что планировщик Go работает поверх планировщика ОС, а не вместо него. Следом обычно спрашивают, что происходит с потоком, когда горутина уходит в блокирующий системный вызов, и как GOMAXPROCS ведёт себя в контейнере.
Как отвечать
Схема M:N: много горутин выполняются на небольшом числе потоков ОС. Участники:
- G: горутина. Стек стартует с 2 КБ и растёт по необходимости, у потока ОС стек обычно измеряется мегабайтами;
- M: поток ОС, его планирует ядро;
- P: логический процессор с локальной очередью горутин. Их число задаёт
GOMAXPROCS, по умолчанию по числу доступных CPU, а с Go 1.25 рантайм на Linux учитывает CPU-лимит cgroup.
Отличия от планировщика ОС:
- где работает: Go переключает горутины в пространстве пользователя, сохраняя несколько регистров. Переключение потока идёт через ядро и стоит заметно дороже;
- что знает: рантайм знает о каналах, мьютексах и сетевом вводе-выводе. Горутина, ждущая канал, паркуется без участия ядра, а сеть обслуживает netpoller поверх epoll или kqueue, так что поток не блокируется;
- балансировка: пустой P ворует половину очереди у соседа (work stealing), есть глобальная очередь;
- блокирующий syscall: M уходит в вызов, а P передаётся другому потоку, чтобы остальные горутины продолжали работу;
- вытеснение: с Go 1.14 асинхронное, по сигналу, горутину снимают примерно через 10 мс. Приоритетов у горутин нет, у потоков ОС есть.
Посмотреть поведение можно через GODEBUG=schedtrace=1000 и go tool trace.
Где спотыкаются
Говорят, что Go обходит планировщик ОС. Потоки M по-прежнему планирует ядро, и если хост перегружен, горутины тоже ждут.
Называют планировщик кооперативным. Это верно только до Go 1.14, сейчас бесконечный цикл без вызовов функций не подвешивает остальные горутины.
Путают GOMAXPROCS с лимитом потоков. Потоков бывает больше из-за syscall и cgo, их предел задаёт debug.SetMaxThreads, по умолчанию 10 000. А в контейнерах на версиях до 1.25 рантайм брал все ядра хоста и ловил троттлинг, поэтому ставили automaxprocs.