Ответ
Системный вызов (syscall) сам по себе — это обращение к ядру ОС, и его стоимость не зависит от того, кто его вызвал. Однако накладные расходы, связанные с блокировкой при системном вызове, кардинально различаются.
В этом сравнении модель с горутинами значительно эффективнее.
Модель с горутинами в Go
- Планировщик M:N: Go использует собственный планировщик, который отображает M горутин на N потоков ОС. Горутины — это легковесные потоки, управляемые рантаймом Go, а не ядром ОС.
- Неблокирующие syscalls: Когда горутина выполняет блокирующий системный вызов (например, чтение из сети), рантайм Go может "увидеть" это. Он открепляет текущий поток ОС (N) от этой горутины и передает его другой готовой к выполнению горутине (M).
- Результат: Переключение контекста происходит между горутинами в рамках одного процесса, что чрезвычайно дёшево. Поток ОС не блокируется и продолжает выполнять полезную работу. Это позволяет эффективно обслуживать тысячи одновременных соединений с небольшим количеством потоков ОС.
Модель с процессами в PostgreSQL (классическая)
- Процесс на соединение: PostgreSQL по умолчанию создает отдельный процесс ОС для каждого клиентского соединения. Каждый процесс имеет собственное адресное пространство и управляется напрямую ядром ОС.
- Блокирующие syscalls: Когда процесс выполняет блокирующий системный вызов, ядро ОС переводит весь процесс в состояние ожидания.
- Результат: Чтобы система продолжила выполнять другую работу, ядро должно выполнить полноценное переключение контекста на другой процесс. Это дорогостоящая операция, включающая смену адресного пространства, таблиц страниц памяти и т.д. Из-за этого масштабирование на десятки тысяч одновременных соединений становится проблематичным и ресурсоемким.
Итог
Характеристика | Go (горутины) | PostgreSQL (процессы) |
---|---|---|
Единица конкурентности | Горутина (легковесная) | Процесс (тяжеловесный) |
Переключение контекста | Дешевое (внутри процесса) | Дорогое (между процессами) |
Реакция на блокировку | Поток ОС выполняет другую горутину | Весь процесс блокируется |
Масштабируемость | Очень высокая | Ограниченная |
Таким образом, накладные расходы, связанные с конкурентной обработкой блокирующих системных вызов, в Go на порядки ниже, чем в традиционной модели "процесс на соединение".