Есть ли интересные нюансы с GOMAXPROCS и cgroups в Linux?
Ответ от нейросети
sobes.tech AI
В Linux при использовании cgroups (control groups) для ограничения ресурсов контейнеров или процессов есть важный нюанс с переменной окружения GOMAXPROCS в Go.
По умолчанию Go рантайм устанавливает GOMAXPROCS равным количеству доступных CPU, которые видит система. Однако в контейнеризованных средах (например, Docker) или при использовании cgroups, ядро может ограничивать доступный процессу CPU, но Go рантайм может не учитывать эти ограничения и считать доступными все CPU хоста.
Это приводит к ситуации, когда GOMAXPROCS больше реального количества доступных CPU, что может вызвать избыточный контекстный переключатель и ухудшение производительности.
Начиная с Go 1.5 и далее, Go пытается автоматически определять ограничения cgroups и устанавливать GOMAXPROCS согласно реальному количеству доступных CPU. Но в некоторых случаях (старые версии Go, специфичные настройки cgroups) этого не происходит.
Рекомендуется явно задавать GOMAXPROCS в контейнерах или использовать библиотеку golang.org/x/sys/unix для чтения ограничений cgroups и динамически устанавливать runtime.GOMAXPROCS.
Пример установки GOMAXPROCS вручную:
import (
"runtime"
"os"
"strconv"
)
func main() {
if val, ok := os.LookupEnv("GOMAXPROCS"); ok {
if n, err := strconv.Atoi(val); err == nil {
runtime.GOMAXPROCS(n)
}
}
// ... остальной код
}
Или использовать пакет automaxprocs от Uber, который автоматически подстраивается под cgroups:
import "go.uber.org/automaxprocs"
func main() {
_, _ = automaxprocs.Set()
// ...
}