Как работает планировщик горутин в Go и что такое work-stealing?

Ответ

Планировщик Go реализует модель мультиплексирования M:N, распределяя большое количество горутин (G) на меньшее количество потоков операционной системы (M). Для этого используется концепция логических процессоров (P).

Ключевые компоненты:

  • G (Goroutine): Легковесный поток, управляемый рантаймом Go.
  • M (Machine): Поток операционной системы (OS thread).
  • P (Processor): Логический процессор, который выступает в роли контекста для выполнения горутин. У каждого P есть своя локальная очередь горутин (LRQ - Local Run Queue).

Процесс перераспределения:

  1. Основной цикл: Поток M берет горутину G из очереди своего процессора P и исполняет её.
  2. Блокировка: Если горутина блокируется (например, на системном вызове или ожидании канала), поток M отсоединяется от P и переходит в режим ожидания вместе с этой горутиной. Рантайм Go старается найти другой свободный M или создать новый, чтобы он продолжил выполнять горутины из очереди P.
  3. Work-Stealing (Воровство работы): Если у процессора P заканчиваются горутины в его локальной очереди, он не простаивает. Вместо этого он пытается "украсть" половину горутин из очереди другого, более загруженного процессора P. Это обеспечивает равномерную загрузку всех ядер CPU.
  4. Кооперативная многозадачность: Горутина может добровольно уступить процессор, вызвав runtime.Gosched(). Кроме того, с версии Go 1.14 планировщик может принудительно вытеснять горутины, которые выполняются слишком долго без блокировок (например, в циклах), вставляя проверку на прерывание при вызове функций.
// Пример, где планировщик может переключить контекст
go func() {
    // Блокирующая операция. В этот момент P освобождается
    // и может взять на исполнение другую горутину.
    time.Sleep(1 * time.Second)
    fmt.Println("Done")
}()

Итог: Механизм work-stealing в сочетании с моделью G-M-P позволяет Go эффективно управлять миллионами горутин с минимальными накладными расходами, достигая высокой производительности в конкурентных приложениях.