GMP深入思考

gmp模型总览(图片来自刘丹冰老师)

在这里插入图片描述

关于gmp本身,已经有优秀的博主做了精彩的讲解,我针对有一定基础,并希望巩固和查漏补缺的人群做一些自己的思考的分享,以Q&A的形式进行探讨

1.G和M就可以实现线程对协程的调度和执行,为什么需要P?

早期的goroutine确实是GM模型,但有很严重的性能问题:

  • 创建、销毁、调度G需要M进行激烈的锁竞争
  • G在不同M之间的转移会损失局部性优势

2.goroutine最终由M调度,那为什么最大并发量不不是由M决定的?
因为M需要绑定到某一个P才能获得g,从而实现调度。此外分别有M、P的空闲队列,因此P也不是完全决定并发量,而是由M和P共同决定,也就是说并发量是由某时刻M-P结合体的数量决定

3.P和M的数量关系,哪个更多一些?
结论 P <= M,P > M没有意义,另外M的数量是动态的,P的上限可以通过环境变量或库函数更改

4.对于被动阻塞的goroutine,比如网络io导致goroutine阻塞了。此时不会被放到一个本地或者全局队列当中,后续就绪事件发生,这个具体是怎么执行,怎么交给g0、m执行的?

这个阻塞的g会被放在应用层的阻塞队列里(由epoll管理),当一个M饥饿时,会依次

1.stealing (每61次从本地队列stealing,强制一次从全局队列获取)

2.全局队列获取

3.根据epoll监听的网络事件,从就绪队列中获取

5.当一个goroutine进行系统调用/阻塞时,会发生什么?

执行该g的M会被动解绑P,该P被重新绑定到另一个M(M先从空闲队列找,找不到则创建),一般不会让P空闲,放入P的空闲队列

阻塞的M,如果其goroutine执行结束,被放入空闲队列,等待被获取

6.g创建后是如何被分配到某一个p的队列中去的呢?

为考虑局部性,g优先投递到当前p的本地队列,满了则进入全局队列

7.goroutine的四种调度类型有什么不同?

  • 主动让出(由用户调用)
    • 主动让出的g会被加入全局队列(为什么?)是为了尽量保证所有g被公平调度,1.此g已经被执行一段时间了 2.用户主动让出说明该g优先级较低
  • 被动调度,即g进行系统调用/阻塞操作而被动让出,同问题5
  • 正常调度,即g执行完成被销毁
  • 抢占调度,有全局监控者(是一个goroutine)负责,独立于调度器。当一个g运行时间超过10ms,会发出抢占的信号,需要运行该g的M的配合才能完成,而非强制抢占

8.感觉主要的调度还是g0完成的,p只是起到了一个存储g的作用,这样理解对吗?

差不多,此外P还实现了per-M 本地 runq、timer、内存分配器(mcache)

9.P是谁创建的?什么时候创建的?数量多少?M呢?

P是由程序初始化时主线程的调度器的函数创建的,数量 == cpu核心数,可以自行修改

M也是初始化主线程的调度器的函数创建的,初始数量为1,M数量是动态增长的,调度器有需要就创建:

1.当前没有空闲 M;

2.有 P 可用,且 runq 有待执行 G;

3.syscall 阻塞了现有 M;

4.有 netpoll 唤醒的 G 需要调度;

M最大值10000,防止资源耗尽,同时绝对大于cpu核心数

…未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjq++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值