Goroutine调度分析(三)
来源:互联网 发布:ug软件怎么下载 编辑:程序博客网 时间:2024/05/17 12:03
上一篇文章中,大致讲了goroutine的C代码数据结构以及大致的调度策略,但是其实上一篇所提到的知识一开始go的设计,还有许多性能上的缺点。高吞吐量的其服务器以及并行运算,显示14%的的时间用在了runtime.futex()。
scheduler 的问题
- 一个全局的互斥锁和集中的状态。互斥锁保护goroutine的操作。
- Goroutine hand-off。工作线程经常之间传递runnable goroutine,这会导致延迟增加,和资源消耗。
- 每一个M都有mcache。其实只有正在运行goroutine的M才需要用到mcache(一个因为系统调用阻塞的M的并不需要mcache)。通常来说跑G code的M和所有的M的数量比有1:100,或者更大。这就导致过多的资源消耗(每一个Mcache占用炒作2MB)。和很差的data locality.
- 过多的线程blocking/unblocking。
设计改进
大致上来说就是增加一个P(Processors)数据结构并且实现一个work-stealing scheduler。
M代表OS线程,P代表一个需要执行Go的资源。当M执行Go code,它必须有一个P。若M是空闲的或者进入系统调用,它也需要P。
确切来讲,总共有GOMAXPROCS 个P。所有的P被组成一个数组,这是work-stealing的要求。一些变量从sched移动到P。一些变量也从M移动到P(一些跟激活go code执行相关的变量)。P数据结构如下图
当一个M准备要执行Go code时,它必须从list中pop一个P。当执行完Go code时,它必须将它的P push到list中。所有当M执行Go code,它必须有一个P。
调度
当新的G被创建或者一个G编程runnable状态。它会被push到当前执行的P。当P执行完一个G,它会先尝试从自己list中pop一个runnable G。如果list是空的,则P选择一个随机的P(不包括自己),且尝试偷一半的runnable goroutine过来。
系统调用/ M Parking 和 Unparking
当M创建一个新的G,必须要保证有一个其他M来执行这个G。类似的,当M进入系统调用,它必须保证有一个其他的M来执行Go code。
这里有两个选择,一个是block 或unblock M, 一个是实现spinning(自旋)。这里有一个性能和消耗不必要CPU周期的冲突。这里的idea是用spinning并且需要消耗cpu周期。尽管如此,当GOMAXPROCES=1时,二者是没有区别的。
Spinning有两个阶段:(1)当有P资源的空闲M寻找新的G (2)当M没有P资源等待可用的P资源时。 这里至多有GOMAXPROCS spinning的M。当有空闲的type(2)造成的空前M时,type(1)产生的M不会阻塞。当有一个G被创建时,或者M进入了系统调用,或M从空闲转为忙碌,它会保证至少有一个spinningM。这就保证了没有runnable goroutine会被执行,并且避免了过多的blocking/unblocking
LockOSThread
- Locked G转为non-runnable。M立即返回P到空闲列表,唤醒其他M并且阻塞
- Locked G 转为runnable。当前M将自己的P和locked G交给跟locked G链接的M,并且Unlock 它。当前的M转为空闲
空闲G
runtime有一个空闲G队列,M会访问这个队列当它有几次失败地偷G的尝试之后。
- Goroutine调度分析(三)
- Goroutine的调度分析(一)
- Goroutine的调度分析(二)
- goroutine与调度器
- goroutine与调度器
- goroutine与调度器
- Goroutine 调度模型猜想
- go-goroutine 调度
- Goroutine 的调度
- golang的goroutine调度机制
- go语言的goroutine调度机制
- Golang1.7 Goroutine源码分析
- goroutine
- goroutine
- [转]Golang中goroutine的调度器详解
- 网狐棋牌(三) 调度引擎初步分析
- Spark源码分析(三)调度管理1
- linux调度器源码分析 - 新进程加入(三)
- UVA 352 The Seasonal War
- Android SDK is missing required platform api in Unity2017.1.1f1
- ros如何及时清除障碍物层或者超声波层的的消息
- C# winform中一个类中如何调用另一个窗体的控件或方法
- linux之零拷贝(ZeroCopy)
- Goroutine调度分析(三)
- POJ:1328 Radar Installation (贪心)
- String数组转List,List转String数组:
- 腾讯测试题-满二叉排序树根节点
- 定义Java中的方法
- 计算“回文数年月日”
- 国庆闲游北京
- 基于FreeRTOS与MQTT的物联网技术应用系列——步进电机控制(七)基于CrossApp跨平台框架的MQTT客户端控制应用android版
- 一条不归路