Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go1.25からのGOMAXPROCS

Avatar for kuro kuro
June 18, 2025

 Go1.25からのGOMAXPROCS

golang.tokyo #39の発表で使ったスライドです。

参考リンク
- golang/go issue#73193: CPU limit-aware GOMAXPROCS default(https://github.com/golang/go/issues/73193)
- uber-go/automaxprocs(https://github.com/uber-go/automaxprocs)
- VictoriaMetrics Blog: Container CPU Requests & Limits Explained with GOMAXPROCS Tuning(https://victoriametrics.com/blog/kubernetes-cpu-go-gomaxprocs/)

Avatar for kuro

kuro

June 18, 2025
Tweet

More Decks by kuro

Other Decks in Programming

Transcript

  1. 1 runtime.NumCPU() GOMAXPROCS = min(ɂțɗǟ๮෯CPUࣂ, CPUȆȹȇȯȪȇɂȝȓǘ෪සό୻ǛCPUࣂ) GOMAXPROCS = min( max(2,

    ceil(cgroupǟCPUࣕ׾)), ɂțɗǟ๮෯CPUࣂ, CPUȆȹȇȯȪȇɂȝȓǘ෪සό୻ǛCPUࣂ )
  2. func defaultGOMAXPROCS(ncpu int32) int32 { // GOMAXPROCS 下 : //

    1. sched_getaffinity CPU // 2. cgroup CPU (quota/period) procs := getCPUCount() // CPU フ if procs <= 0 { procs = getCPUCount() } if !cgroupOK { return procs // cgroup } return adjustCgroupGOMAXPROCS(procs, cgroupCPU) }
  3. func adjustCgroupGOMAXPROCS(procs int32, cpu cgroup.CPU) int32 { limit, ok, err

    := cgroup.ReadCPULimit(cpu) if err == nil && ok { limit = ceil(limit) // limit = max(limit, 2) // 2 if int32(limit) < procs { procs = int32(limit) // } } return procs }
  4. func sysmonUpdateGOMAXPROCS() { // GOMAXPROCS ック lock(&computeMaxProcsLock) // GOMAXPROCS lock(&sched.lock)

    custom := sched.customGOMAXPROCS // フ curr := gomaxprocs // GOMAXPROCS unlock(&sched.lock) if custom { unlock(&computeMaxProcsLock) return // } // フ ス sched.lock procs := defaultGOMAXPROCS(0) // cgroup unlock(&computeMaxProcsLock)
  5. if procs == curr { return // 何 } //

    STW パ Goroutine ス if updateMaxProcsG.idle.Load() { lock(&updateMaxProcsG.lock) updateMaxProcsG.procs = procs // updateMaxProcsG.idle.Store(false) var list gList list.push(updateMaxProcsG.g) // パ Goroutine 実 injectglist(&list) unlock(&updateMaxProcsG.lock) } }
  6. func updateMaxProcsGoroutine() { // updateMaxProcsG.g = getg() // ... for

    { // sysmon lock(&updateMaxProcsG.lock) updateMaxProcsG.idle.Store(true) goparkunlock(&updateMaxProcsG.lock, waitReasonUpdateGOMAXPROCSIdle, traceBlockSystemGoroutine, 1) // sysmon // STW stw := stopTheWorldGC(stwGOMAXPROCS)
  7. // STW lock(&sched.lock) custom := sched.customGOMAXPROCS unlock(&sched.lock) if custom {

    startTheWorldGC(stw) return // } // newprocs startTheWorld newprocs = updateMaxProcsG.procs lock(&sched.lock) sched.customGOMAXPROCS = false // フ ッ unlock(&sched.lock) startTheWorldGC(stw) // STW } }