Are there interesting nuances with GOMAXPROCS and cgroups in Linux?
sobes.tech AI
Answer from AI
In Linux, when using cgroups (control groups) to limit resources for containers or processes, there is an important nuance with the environment variable GOMAXPROCS in Go.
By default, the Go runtime sets GOMAXPROCS to the number of available CPUs that the system sees. However, in containerized environments (such as Docker) or when using cgroups, the kernel may restrict the process's accessible CPUs, but the Go runtime might not account for these restrictions and consider all host CPUs available.
This leads to a situation where GOMAXPROCS is greater than the actual number of accessible CPUs, which can cause excessive context switching and degrade performance.
Starting from Go 1.5 and later, Go attempts to automatically detect cgroup restrictions and set GOMAXPROCS according to the actual number of available CPUs. But in some cases (older Go versions, specific cgroup settings), this does not happen.
It is recommended to explicitly set GOMAXPROCS in containers or use the golang.org/x/sys/unix library to read cgroup restrictions and dynamically set runtime.GOMAXPROCS.
Example of manually setting 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)
}
}
// ... rest of the code
}
Or use the automaxprocs package from Uber, which automatically adjusts to cgroups:
import "go.uber.org/automaxprocs"
func main() {
_, _ = automaxprocs.Set()
// ...
}