Skip to content

Golang面试题:sysmon 有什么作用

协作式的抢占式调度

在1.14 版本之前,程序只能依靠 Goroutine 主动让出 CPU 资源才能触发调度,存在问题

  • 某些 Goroutine 可以⻓时间占用线程,造成其它 Goroutine 的饥饿
  • 垃圾回收需要暂停整个程序(Stop-the-world,STW),最⻓可能需要几分钟的时间,导致整个程序无法工作。

基于信号的抢占式调度

在任何情况下,Go运行时并行执行(注意,不是并发)的 goroutines 数量是小于等于 P 的数量的。为了提高系统 的性能,P 的数量肯定不是越小越好,所以官方默认值就是 CPU 的核心数,设置的过小的话,如果一个持有 P 的 M,由于 P 当前执行的 G 调用了 syscall 而导致 M 被阻塞,那么此时关键点: GO 的调度器是迟钝的,它很可能什 么都没做,直到 M 阻塞了相当⻓时间以后,才会发现有一个 P/M 被 syscall 阻塞了。然后,才会用空闲的 M 来强 这个 P。通过 sysmon 监控实现的抢占式调度,最快在20us,最慢在10-20ms才会发现有一个 M 持有 P 并阻塞 了。操作系统在1ms 内可以完成很多次线程调度(一般情况1ms可以完成几十次线程调度),Go 发起 IO/syscall 的时候执行该 G 的 M 会阻塞然后被 OS调度走,P什么也不干,sysmon 最慢要10-20ms 才能发现这个阻塞,说不 定那时候阻塞已经结束了,宝贵的 P资源就这么被阻塞的 M浪费了。

sysmon 有什么作用

sysmon 也叫监控线程,变动的周期性检查,好处

  • 释放闲置超过5 分钟的 span 物理内存;
  • 如果超过2 分钟没有垃圾回收,强制执行;
  • 将⻓时间未处理的 netpoll 添加到全局队列;
  • 向⻓时间运行的 G 任务发出抢占调度(超过10ms的 g,会进行 retake);
  • 收回因 syscall ⻓时间阻塞的 P;