Senior
423
questionbank

Как устроен runtime в языке Go?

Получайте ответы на вопросы в реальном времени с Sobes Copilot
Ответ от нейросети sobes.tech

Runtime в Go — это система времени выполнения, которая управляет выполнением Go-программ. Она отвечает за:

  • Планирование: Использует планировщик M:N, который связывает M легковесных горутин с N системными потоками ОС. Это позволяет эффективно использовать ядра процессора.
  • Управление памятью: Реализует автоматический сборщик мусора (GC), который периодически высвобождает неиспользуемую память. GC в Go — Concurrent, Tri-color Mark-and-sweep, что позволяет ему работать одновременно с пользовательским кодом и сокращать паузы.
  • Управление горутинами: Создание, выполнение, переключение контекста и завершение горутин. Горутины легче потоков ОС, их создание и переключение контекста менее затратно.
  • Каналы (Channels): Реализует механизм синхронизации и обмена данными между горутинами. Каналы могут быть буферизованными или небуферизованными.
  • Сетевые операции: Встроенные примитивы для работы с сетью, которые интегрированы с планировщиком.
  • Системные вызовы: Абстрагирует взаимодействие с операционной системой.

Основные компоненты планировщика:

  • M (Machine): Поток ОС.
  • P (Processor): Логический процессор, представляющий контекст, в котором выполняются горутины (G). Каждый P имеет локальную очередь готовых к выполнению горутин (runqueue). Количество P по умолчанию равно runtime.NumCPU().
  • G (Goroutine): Легковесный поток выполнения.

Когда горутина готова к выполнению, она помещается в локальную очередь P. Если локальная очередь P пуста, планировщик может "украсть" горутину из очереди другого P (work stealing). Если все P заняты и их локальные очереди пусты, планировщик может забрать горутину из глобальной очереди.

Операции ввода/вывода блокирующие для горутин, но не для потоков ОС. Когда горутина выполняет блокирующий системный вызов, она отключается от своего P, а планировщик подключает к этому P другую готовую горутину. Поток ОС (M) становится блокированным, пока системный вызов не завершится. После завершения системного вызова горутина снова становится доступной для планирования и может быть назначена на любой свободный P.

Пример создания горутины:

go

Пример использования канала:

go