GO scheduler
2023-10-09 21:15:59 23 举报
AI智能生成
Go 调度相关硬核知识
作者其他创作
大纲/内容
监控线程
sysmon 的启动
sysmon作用
GC
通知GC:垃圾回收器超过2分钟没有执行的话,sysmon 监控线程也会强制进行GC。
归还内存:每5分钟归还GC后不再使用的span给操作系统(scavenge)
保证timer 运行,查看应该在运行却仍在等待执行的计时器timer,尽可能快地运行它们.
打印调度信息
监控 netpoller ,定时从 netpoller 中获取 ready 的协程,放入 GRQ
Preemption:执行抢占
监控系统调用:将 P 与 M 脱离
非系统调用,通知抢占
执行
其周期 (循环时间) 是动态的,取决于正在运行的程序的当前活动。
不运行,进入休眠
垃圾回收器即将要运行. (sysmon线程将在垃圾回收结束时恢复)
所有线程都处于空闲状态,没有任何一个在运行中
G 抢占
提问
goroutine没有优先级么?是的
什么时候需要抢占?
如何抢占,新老抢占的实现有何不同?
抢占的触发时机
GC STW
栈扫描
监控线程 sysmon 触发
抢占的实现
老版本-协作式抢占
preemptone 函数只做标记⼯作
检查当前栈空间是否⾜够,不够的话,需要申请新的栈空间
保存当前goroutine的运⾏现场,切换到m.g0,执⾏newstack
gopreempt_m将当前的goroutine放进了全局队列
新版本 - 信号式抢占
preemptone 函数:通过系统调⽤ tgkill 函数,给特定的线程发信号
处理 SIGURG 信号时,相当于被强⾏插⼊⼀条 asyncPreempt 的函数调⽤
推荐
曹大 抢占调度PPT
曹大 抢占调度
实际应用
为什么Go服务容器化之后延迟变高?
原因:Go服务容器化的 P 数量问题
解决方案:引入 uber 的 automaxprocs 库
Go服务最好不要用太多的CPU
参考资料
Golden Go调度篇
深入浅出GolangRuntime
为什么Go服务容器化之后延迟变高
Go 为什么这么“快”
Golang 的 goroutine 是如何实现的?
Golang sysmon监控线程
引言
什么是调度?
运行&阻塞
演化:Process -> Thread(LWP, lightweight process) -> Goroutine (一种lightweight userspace thread) =》一个不断共享、不断减少切换成本的过程.
思考问题
怎样实现少量内核线程支撑大量 Goroutine 的并发运行?
为什么说Go调度Goroutine是轻量的?
上下文切换代价小
内存占用少
调度模型
基本概念
G:goroutine 一个计算任务
M: machine 系统线程
P: processor 虚拟处理器
GM模型(go 1.0)
全局调度锁问题
G 的传递问题
Per-M 的内存问题
GMP 模型(go 1.0 +)
交互形式
简图
源码 1
源码 2
详情
全景大图
G状态流转
G 状态列表
G 状态流转图
举例说明
调度器
调度循环(Schedule loop)
M 执行 G 时四个方法周而复始
队列优先级: runnext > local run queue > global run queue > other p local run queue
调度策略
hand off 机制: 当本线程因为 G 进行系统调用阻塞时,线程释放绑定的 P,把 P 转移给其他空闲的线程执行。
work-stealing 机制:当本线程无可运行的 G 时,尝试从其他线程绑定的 P 偷取 G,而不是销毁线程
调度过程
调度时机
调度优化
提问 🙋
为了最大限度利用计算资源,Go 调度器是如何处理线程阻塞的场景?
原子、互斥量(锁)、通道操作:切换阻塞 G
网络 IO 请求:让 netpoll 去处理,切换阻塞 G
step 1
step 2
step 3
网络轮询器 netpoller
syscall 调用:监控线程 sysmon 会监控识别,将 P 与 M 脱离,让 P 与其他空闲M结合
step 1
step2
step 3
sleep 操作:监控线程 sysmon,会监控那些长时间运行的 G 任务,会进行抢占操作
0 条评论
下一页