package main import ( "fmt" "log" "net/http" _ "net/http/pprof" "sync" "time" )
func main() { go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() wg := sync.WaitGroup{} fmt.Println("see cpu profile") ch := make(chan struct{}) time.AfterFunc(time.Second*60, func() { close(ch) }) for i := 0; i <= 1000000; i++ { wg.Add(1) go func() { defer wg.Done() ticker := time.NewTicker(time.Millisecond * 1000) defer ticker.Stop() for { select { case <-ticker.C: // do something case <-ch: return } } }() } fmt.Println("waiting...") wg.Wait() fmt.Println("all done") } The snippet demonstrate millions of workers do something in parallel. Everyone hold a time ticker to check job per second. Though it is kind of ridiculous in real life. The code works well a few days ago in Linux Mint 19(Ubuntu 18.04). It take 60-70% CPU usage of six-core Intel I5-8500T. Once I run the code, I see the kernel take about 85% CPU(RED bar in htop) and left 15% for user(GREEN bar in htop). I try to debug using pprof. Type: cpu Time: Nov 29, 2018 at 8:56pm (CST) Duration: 45.20s, Total samples = 1.55mins (206.39%) Entering interactive mode (type "help" for commands, "o" for options) (pprof) top Showing nodes accounting for 90.80s, 97.34% of 93.28s total Dropped 38 nodes (cum <= 0.47s) Showing top 10 nodes out of 16 flat flat% sum% cum cum% 83.20s 89.19% 89.19% 83.25s 89.25% time.now 3.58s 3.84% 93.03% 3.58s 3.84% runtime.procyield 1.44s 1.54% 94.58% 1.44s 1.54% runtime._VDSO 1.04s 1.11% 95.69% 1.04s 1.11% runtime.siftdownTimer 0.69s 0.74% 96.43% 4.46s 4.78% runtime.lock 0.41s 0.44% 96.87% 5.49s 5.89% runtime.selectgo 0.16s 0.17% 97.04% 0.51s 0.55% runtime.schedule 0.11s 0.12% 97.16% 0.85s 0.91% runtime.chansend 0.10s 0.11% 97.27% 4.34s 4.65% runtime.sellock 0.07s 0.075% 97.34% 5.58s 5.98% main.main.func3 (pprof) list time.now Total: 1.55mins ROUTINE ======================== time.now in /usr/local/go/src/runtime/timestub.go 1.39mins 1.39mins (flat, cum) 89.25% of Total . . 11: . . 12:import _ "unsafe" // for go:linkname . . 13: . . 14://go:linkname time_now time.now . . 15:func time_now() (sec int64, nsec int32, mono int64) { 47.56s 47.58s 16: sec, nsec = walltime() 35.64s 35.67s 17: return sec, nsec, nanotime() - startNano . . 18:} Here you can see *time.now* take almost CPU time. After reboot it is work well as usually. see profile below. Type: cpu Time: Nov 28, 2018 at 11:07pm (CST) Duration: 30.13s, Total samples = 58.85s (195.33%) Entering interactive mode (type "help" for commands, "o" for options) (pprof) top Showing nodes accounting for 47840ms, 81.29% of 58850ms total Dropped 110 nodes (cum <= 294.25ms) Showing top 10 nodes out of 67 flat flat% sum% cum cum% 26080ms 44.32% 44.32% 26080ms 44.32% runtime.procyield 6050ms 10.28% 54.60% 6050ms 10.28% runtime.futex 3990ms 6.78% 61.38% 31100ms 52.85% runtime.lock 2640ms 4.49% 65.86% 36480ms 61.99% runtime.selectgo 2290ms 3.89% 69.75% 3080ms 5.23% runtime.unlock 2070ms 3.52% 73.27% 2080ms 3.53% runtime.siftdownTimer 1450ms 2.46% 75.73% 1450ms 2.46% runtime.casgstatus 1230ms 2.09% 77.82% 1280ms 2.18% runtime.gopark 1120ms 1.90% 79.73% 1120ms 1.90% runtime.(*waitq).dequeue 920ms 1.56% 81.29% 940ms 1.60% time.now I also run the code in MacOS 10.13 and Windows 10 as I expected. It works well. So is it a bug belongs to kernel or golang? even hardware? Hardware: Dell OptiPlex 7060 micro, Intel Core I5 8500T, 8G RAM Linux Mint 19(Ubuntu 18.04) with shipped kernel: Linux HOSTNAME 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux Go version: go version go1.11.2 linux/amd64 GOARCH="amd64" GOBIN="" GOCACHE="/home/USER/.cache/go-build" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOOS="linux" GOPATH="/home/USER/go" GOPROXY="" GORACE="" GOROOT="/usr/local/go" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64" GCCGO="gccgo" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build427891521=/tmp/go-build -gno-record-gcc-switches" -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.