繁体   English   中英

使用GOMAXPROCS = 256运行无限循环goroutine时理解golang的调度程序

[英]Making sense of golang's scheduler when running infinite-loop goroutines with GOMAXPROCS = 256

我正在玩Go,在2015年的8核MacBookPro上运行go 1.7.3。

试图弄清楚运行时的go调度程序是如何工作的。将GOMAXPROCS设置为其最大值(256),并启动相同数量的goroutine,每个goroutine运行一个无限循环。

我的假设是go runtime将产生runtime.GOMAXPROCS操作系统线程数(即256个线程),并在这些线程中运行我的goroutine。

我期望以下代码可以打印256个1:

func main() {
    procs := 256
    runtime.GOMAXPROCS(procs)
    for i := 0; i < procs; i++ {
        go func() {
            fmt.Print("1")
            for {}
        }()
    }
    for {}
}

每次运行时,此代码都会打印各种数字1。 大多数情况下,它会打印142 1。

现在,有一个runtime.Gosched()可以手动调用go调度程序。 我玩它,我发现我可以得到256 1的印刷只有当我打电话runtime.Gosched() 两个够程主要FUNC:

func main() {
    procs := 256
    runtime.GOMAXPROCS(procs)
    for i := 0; i < procs; i++ {
        go func() {
            fmt.Print("1")
            for { runtime.Gosched() }
        }()
    }
    for { runtime.Gosched() }
}

有人可以解释为什么默认情况下不打印256 1且我需要runtime.Gosched()吗? 我们不应该让256个OS线程来运行这256个goroutine吗? 为什么我们需要在两个地方都调用runtime.Gosched()?

我认为这是因为可以在计算机上创建的线程数量有限。 runtime.GOMAXPROCS(256)作用是创建256个逻辑处理器 (也称为P =处理器)并尝试运行它们。 每个P都有自己的名为G的goroutine的运行队列,并由OS线程(称为M的Machine)执行。

因此,发生的事情是您的256个P试图让一个OS线程( M )执行G ,但是您的计算机没有那么多资源来运行256个OS线程,因此,为什么只有143个。

对我来说,执行此命令会产生143个,此进程的运行线程数约为150。

因为默认情况下,go Scheduler不会抢占任何goroutine,所以您只能运行大约150个goroutine,而其他所有goroutine都将饿死于OS线程。 这是描述此行为的问题 调用runtime.Gosched()产生处理器( P ),从而允许其他goroutine运行。

要检查调度程序在做什么,您可以添加GODEBUG环境变量:

env GODEBUG=scheddetail=1,schedtrace=1000 ./cpu3

这是输出(请注意,它使用P,M,G术语 ):

SCHED 0ms: gomaxprocs=8 idleprocs=5 threads=5 spinningthreads=1 idlethreads=0 runqueue=0 gcwaiting=0 nmidlelocked=1 stopwait=0 sysmonwait=0
  P0: status=1 schedtick=0 syscalltick=0 m=3 runqsize=0 gfreecnt=0
  P1: status=1 schedtick=1 syscalltick=0 m=2 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 helpgc=0 spinning=true blocked=false lockedg=-1
  M3: p=0 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 helpgc=0 spinning=false blocked=false lockedg=-1
  M2: p=1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 helpgc=0 spinning=true blocked=false lockedg=-1
  M1: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=1 dying=0 helpgc=0 spinning=false blocked=false lockedg=-1
  M0: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 helpgc=0 spinning=false blocked=true lockedg=1
  G1: status=1(chan receive) m=-1 lockedm=0
  G2: status=4(force gc (idle)) m=-1 lockedm=-1
  G3: status=4(GC sweep wait) m=-1 lockedm=-1
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111SCHED 1004ms: gomaxprocs=256 idleprocs=0 threads=150 spinningthreads=0 idlethreads=5 runqueue=0 gcwaiting=1 nmidlelocked=0 stopwait=143 sysmonwait=0
  P0: status=1 schedtick=1 syscalltick=3 m=0 runqsize=0 gfreecnt=0
  P1: status=1 schedtick=3 syscalltick=1 m=2 runqsize=0 gfreecnt=0
  ...
  P141: status=1 schedtick=3 syscalltick=1 m=143 runqsize=0 gfreecnt=0
  P142: status=1 schedtick=2 syscalltick=3 m=144 runqsize=0 gfreecnt=0
  P143: status=3 schedtick=1 syscalltick=38 m=-1 runqsize=0 gfreecnt=0
  ...
  P255: status=3 schedtick=0 syscalltick=0 m=-1 runqsize=0 gfreecnt=0
  M149: p=-1 curg=-1 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 helpgc=0 spinning=false blocked=true lockedg=-1
  ...
  M144: p=142 curg=181 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 helpgc=0 spinning=false blocked=false lockedg=-1
  M143: p=141 curg=177 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 helpgc=0 spinning=false blocked=false lockedg=-1
  M142: p=140 curg=179 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 helpgc=0 spinning=false blocked=false lockedg=-1
  ...
  M112: p=110 curg=186 mallocing=0 throwing=0 preemptoff= locks=0 dying=0 helpgc=0 spinning=false blocked=false lockedg=-1
  ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM