Skip to content

Instantly share code, notes, and snippets.

@Harold2017
Created June 25, 2019 04:48
Show Gist options
  • Save Harold2017/759673302507cb5b3617a1e36025dac7 to your computer and use it in GitHub Desktop.
Save Harold2017/759673302507cb5b3617a1e36025dac7 to your computer and use it in GitHub Desktop.
golang cpu usage in docker

Golang CPU usage in docker

// 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment