За что отвечает переменная окружения GOMAXPROCS в Go и нужно ли ее менять?

Ответ

GOMAXPROCS — это переменная окружения (или функция в пакете runtime), которая определяет максимальное количество потоков операционной системы (OS threads), которые могут одновременно исполнять код Go.

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

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

  2. Параллелизм, а не конкурентность: GOMAXPROCS управляет именно параллелизмом — реальным одновременным выполнением задач на разных ядрах процессора. Это не влияет на конкурентность — способность программы структурировать код для независимой работы над несколькими задачами (например, с помощью горутин).

  3. Когда это могло быть полезно?

    • До Go 1.5: Значение по умолчанию было 1, и его почти всегда нужно было увеличивать для CPU-bound задач.
    • Современные нишевые случаи: Иногда его могут изменять в средах с неверно определенными лимитами CPU (некоторые старые версии Docker/Kubernetes) или для специфических бенчмарков, чтобы ограничить ресурсы.

Пример использования (для демонстрации, не для продакшена):

package main

import (
    "fmt"
    "runtime"
)

func main() {
    // Получаем текущее значение (обычно равно кол-ву ядер)
    fmt.Printf("Default GOMAXPROCS: %dn", runtime.GOMAXPROCS(0))

    // Устанавливаем новое значение
    runtime.GOMAXPROCS(2)

    // Проверяем, что значение изменилось
    fmt.Printf("New GOMAXPROCS: %dn", runtime.GOMAXPROCS(0))
}

Вывод: В современной разработке на Go изменять GOMAXPROCS — это антипаттерн для 99% случаев. Планировщик Go достаточно умен, чтобы эффективно использовать все доступные ядра.

Ответ 18+ 🔞

Так, слушай, про эту вашу GOMAXPROCS сейчас всё разжую, как есть. Ситуация, в общем-то, проще пареной репы, но вокруг неё такой ореол мистический нарос, будто это какой-то священный рычаг производительности.

Короче, это такая штука, которая говорит рантайму Го: «Слышь, дружок, вот столько потоков операционки ты можешь взять и одновременно гонять на них наш код». Ключевое слово — одновременно. Это про то, чтобы загрузить все ядра твоего процессора, если работа CPU-bound.

Но вот в чём прикол, ёпта. Начиная с Го 1.5 (а это было, мать его, сто лет назад!) эта переменная по умолчанию равна количеству твоих логических ядер. То есть runtime.NumCPU(). Компилятор уже не дебил, он сам всё понимает. И в абсолютном большинстве случаев тебе на неё вообще срать, извини за выражение. Трогать её — это сейчас признак того, что человек либо читал туториал 2012 года, либо он слишком умный и хочет всё оптимизировать, не понимая, как оно работает.

Раньше-то, да, до 1.5, по умолчанию стояла единица. И все бегали, кричали «GOMAXPROCS! Надо увеличить GOMAXPROCS!». А сейчас — ни хуя себе, — всё уже настроено.

Важно не путать, блядь. Это про параллелизм — реальное «вжух» на нескольких ядрах. А не про конкурентность. Конкурентность — это когда у тебя тысяча горутин может болтаться, переключаясь на одном ядре. Это две большие разницы, как говорят в Одессе.

Ну а когда это всё-таки полезно? Ну, кроме как для академического интереса или бенчмарков, где ты хочешь искусственно ограничить ресурсы («а что будет, если я дам ему только одно ядро?»)... Может, в каких-то ебнутых контейнерах, где лимиты CPU криво проставляются, и Го видит не то, что есть на самом деле. Но это такие нишевые случаи, что про них даже говорить смешно.

Вот, смотри, как это выглядит в коде, если тебе вдруг приспичило поиграться:

package main

import (
    "fmt"
    "runtime"
)

func main() {
    // Спрашиваем текущее значение (ноль как аргумент — значит «дай, что есть»)
    fmt.Printf("Дефолтный GOMAXPROCS: %dn", runtime.GOMAXPROCS(0))

    // Ну давай, установим двойку, будь мужиком!
    runtime.GOMAXPROCS(2)

    // Проверим, послушался ли он нас
    fmt.Printf("Новый GOMAXPROCS: %dn", runtime.GOMAXPROCS(0))
}

Итог, блядь, простой, как три копейки: Не лезь туда, мудак. Оставь это значение в покое. Планировщик Го — не дурак, он сам всё раскидает по ядрам эффективнее, чем ты со своими кривыми руками. Всё, что ты сделаешь, поменяв это число — это, с большой вероятностью, только хуже сделаешь. Доверяй языку, ебать.