// test.go
package main
import (
"fmt"
_ "go.uber.org/automaxprocs"
"runtime"
"time"
)
func main() {
fmt.Println(runtime.NumCPU())
time.Sleep(time.Second)
fmt.Println("test")
}
/wip # GODEBUG=schedtrace=100,scheddetail=1 ./auto_maxprocs
SCHED 0ms: gomaxprocs=8 idleprocs=6 threads=5 spinningthreads=1 idlethreads=1 runqueue=0 gcwaiting=0 nmidlelocked=0 stopwait=0 sysmonwait=0
P0: status=1 schedtick=1 syscalltick=0 m=0 runqsize=0 gfreecnt=0
P1: status=0 schedtick=1 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
P2: status=1 schedtick=0 syscalltick=0 m=4 runqsize=0 gfreecnt=0
P3: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
P4: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
P5: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
P6: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
P7: status=0 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
M4: p=2 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=true blocked=false lockedg=-1
M3: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=-1
M2: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1
M1: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1
M0: p=-1 curg=1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=false lockedg=1
G1: status=3(chan receive) m=0 lockedm=0
G2: status=4(force gc (idle)) m=-1 lockedm=-1
G3: status=4(GC sweep wait) m=-1 lockedm=-1
G4: status=1() m=-1 lockedm=-1
2019/06/25 04:45:16 maxprocs: Updating GOMAXPROCS=1: determined from CPU quota
8
SCHED 107ms: gomaxprocs=1 idleprocs=1 threads=5 spinningthreads=0 idlethreads=3 runqueue=0 gcwaiting=0 nmidlelocked=0 stopwait=0 sysmonwait=0
P0: status=0 schedtick=1 syscalltick=29 m=-1 runqsize=0 gfreecnt=0
M4: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=-1
M3: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=-1
M2: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=-1
M1: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 spinning=false blocked=false lockedg=-1
M0: p=-1 curg=5 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 spinning=false blocked=true lockedg=-1
G1: status=4(sleep) m=-1 lockedm=-1
G2: status=4(force gc (idle)) m=-1 lockedm=-1
G3: status=4(GC sweep wait) m=-1 lockedm=-1
G4: status=4(finalizer wait) m=-1 lockedm=-1
G5: status=3() m=0 lockedm=-1
// ...
- if not limit GOMAXPROCS like raw_maxprocs.go, golang will use runtime.NumCPU() as default
- with limit GOMAXPROCS like automaxprocs does, after executing init function, the GOMAXPROCS is set to docker cpu limit and this process requires some time.
- but after test large computing work with docker cpu limit 1 and change GOMAXPROCS set, if watch from docker stats, the cpu usage is only 100% but it was running on GOMAXPROCS cores with 100%/GOMAXPROCS cpu usage.
so cpu limit in docker can limit the cpu usage of golang but the whole process will be running on GOMAXPROCS (default = runtime.NumCPU()) cores with a CPU usage = limit / GOMAXPROCS, which will cost much on context switch and leads to a poor performance, then auto-maxprocs is useful to avoid this performance loss.