Сравните накладные расходы на системные вызовы (syscall) в модели с процессами (например, PostgreSQL) и в модели с горутинами (Go).

Ответ

Системный вызов (syscall) сам по себе — это обращение к ядру ОС, и его стоимость не зависит от того, кто его вызвал. Однако накладные расходы, связанные с блокировкой при системном вызове, кардинально различаются.

В этом сравнении модель с горутинами значительно эффективнее.

Модель с горутинами в Go

  1. Планировщик M:N: Go использует собственный планировщик, который отображает M горутин на N потоков ОС. Горутины — это легковесные потоки, управляемые рантаймом Go, а не ядром ОС.
  2. Неблокирующие syscalls: Когда горутина выполняет блокирующий системный вызов (например, чтение из сети), рантайм Go может "увидеть" это. Он открепляет текущий поток ОС (N) от этой горутины и передает его другой готовой к выполнению горутине (M).
  3. Результат: Переключение контекста происходит между горутинами в рамках одного процесса, что чрезвычайно дёшево. Поток ОС не блокируется и продолжает выполнять полезную работу. Это позволяет эффективно обслуживать тысячи одновременных соединений с небольшим количеством потоков ОС.

Модель с процессами в PostgreSQL (классическая)

  1. Процесс на соединение: PostgreSQL по умолчанию создает отдельный процесс ОС для каждого клиентского соединения. Каждый процесс имеет собственное адресное пространство и управляется напрямую ядром ОС.
  2. Блокирующие syscalls: Когда процесс выполняет блокирующий системный вызов, ядро ОС переводит весь процесс в состояние ожидания.
  3. Результат: Чтобы система продолжила выполнять другую работу, ядро должно выполнить полноценное переключение контекста на другой процесс. Это дорогостоящая операция, включающая смену адресного пространства, таблиц страниц памяти и т.д. Из-за этого масштабирование на десятки тысяч одновременных соединений становится проблематичным и ресурсоемким.

Итог

Характеристика Go (горутины) PostgreSQL (процессы)
Единица конкурентности Горутина (легковесная) Процесс (тяжеловесный)
Переключение контекста Дешевое (внутри процесса) Дорогое (между процессами)
Реакция на блокировку Поток ОС выполняет другую горутину Весь процесс блокируется
Масштабируемость Очень высокая Ограниченная

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