В каких случаях и зачем используется `runtime.GOMAXPROCS`?

Ответ

runtime.GOMAXPROCS(n) устанавливает максимальное количество потоков ОС, которые могут одновременно исполнять код Go. Начиная с Go 1.5, по умолчанию это значение равно количеству доступных ядер ЦП (runtime.NumCPU()).

Изменять значение по умолчанию стоит только в особых случаях:

  1. Ограничение потребления ресурсов. В контейнеризированных средах (Docker, Kubernetes) или на серверах с множеством приложений, чтобы ограничить потребление CPU вашим сервисом и не мешать другим процессам.
  2. Тестирование и отладка. Для эмуляции работы на машинах с меньшим количеством ядер и выявления проблем с конкурентностью, которые проявляются только при определенной степени параллелизма.
  3. Оптимизация специфичных нагрузок. В редких случаях, для CPU-bound приложений с высокой борьбой за блокировки (lock contention), уменьшение GOMAXPROCS может парадоксальным образом увеличить производительность за счет снижения накладных расходов на переключение контекста между ядрами.
  4. Предсказуемое бенчмаркирование. Чтобы получить стабильные и сравнимые результаты тестов производительности на разных машинах.

Как устанавливать?

  • В коде: runtime.GOMAXPROCS(n) (обычно вызывается один раз в main)
  • Через переменную окружения: GOMAXPROCS=n (более гибкий способ для эксплуатации)
package main

import (
    "fmt"
    "runtime"
)

func main() {
    // Устанавливаем использование не более 2 потоков ОС
    // В реальном приложении лучше использовать переменную окружения
    runtime.GOMAXPROCS(2)
    fmt.Printf("GOMAXPROCS set to %dn", runtime.GOMAXPROCS(0))
}

Важно: В большинстве современных приложений изменять GOMAXPROCS не требуется, так как значение по умолчанию является оптимальным.