更新时间:

#在 Go语言程序运行时(runtime)实现了一个小型的任务调度器。这套调度器的工作原理类似于操作系统调度线程,Go 程序调度器可以高效地将 CPU 资源分配给

在 Go语言程序运行时(runtime)实现了一个小型的任务调度器。这套调度器的工作原理类似于操作系统调度线程,Go 程序调度器可以高效地将 CPU 资源分配给每一个任务。传统逻辑中,开发者需要维护线程池中线程与 CPU 核心数量的对应关系。同样的,Go 地中也可以通过 runtime.GOMAXPROCS() 函数做到

对应GMP模型中的P的数量。

但k8s中, runtime.NumCPU() 无法正确获取到容器被分配的 CPU 资源数。runtime.NumCPU()获取的是宿主机的核心数。 设置 GOMAXPROCS 高于真正可使用的核心数后会导致Go调度器不停地进行OS线程切换,从而给调度器增加很多不必要的工作。

而 Uber 提出了一种 Workaround 方法,利用 uber-go/automaxprocs 这一个包,可以在运行时根据 cgroup 为容器分配的CPU资源限制数来修改 GOMAXPROCS。


如果一个M调用了什么API导致了操作系统线程阻塞了,操作系统立刻会把这个线程M调度走,挂起等阻塞解除。这时候,Go调度器不会马上把这个M持有的P抢走。这就会导致一定的P被浪费了。 这就是为何,GOMAXPROCS 太小,也就是P的数量太少,会导致IO密集(或者syscall较多)的go程序运行缓慢的原因。 那么,GOMAXPROCS 很大,超过硬件线程的8倍,会不会有开销呢? 答案是,开销是有的,但是远小于Go运行时迟钝的调度M来抢夺P而导致CPU利用不足的开销。


#评论

#评论 1 · 2023-03-28T02:40:14.517000Z

https://juejin.cn/post/6859333910657138695

#评论 2 · 2023-03-28T02:40:18.714000Z

https://github.com/uber-go/automaxprocs