【golang】调度系列之sysmon
调度系列
调度系列之goroutine
调度系列之m
调度系列之p
在golang的调度体系中,除了GMP本身,还有另外一个比较重要的角色sysmon。实际上,除了GMP和sysmon,runtime中还有一个全局的调度器对象。但该对象只是维护一些全局的数据,而不承担实际的调度职责,并不值得单独介绍,感兴趣的同学可以自己了解一下。
回到sysmon,sysmon是一个管理线程或者说守护线程,其是对GMP调度架构的补充和兜底。通过前面的几篇介绍,可以知道GMP的调度完全是主动协作式的调度。主动协作式的调度性能很高,但是在某些情况下会出现单个goroutine长期占据时间片甚至一直占据时间片的情况。
比如:
- 某个goroutine不执行主动调度、不调用系统调用、不做函数调用,就会一直运行直到goroutine退出;
- 某个goroutine处于syscall状态时也无法触发主动调度,可能会造成该goroutine长时间占据时间片;
sysmon的作用就是处理类似上面情况,其主要的工作内容有:
- 定期查看netpoll有无就绪的任务,防止netpoll阻塞队列中的goroutine饥饿;
- 定期查看是否有p长时间(10ms)处于syscall状态,如有则将p的持有权释放以执行其他g;
- 定期查看是否有p长时间(10ms)没有调度,如有则对当前m发送信号,触发基于信号的异步抢占调度;
在main函数启动时,会调用newm函数创建sysmon线程,sysmon作为mstartfn传入。
// src/runtime/proc.go 145
// The main goroutine.
func main() {...if GOARCH != "wasm" { // no threads on wasm yet, so no sysmonsystemstack(func() {newm(sysmon, nil, -1)})}...
}
在介绍m的时候,我们提到过,mstart中会先调用mstartfn,然后再获取p并调用schedule函数。由于sysmon函数是循环不返回的,所以对应的m(也就是线程)永远运行sysmon,并且不需要获取p。所以并不是所有的m都需要p才可以运行的。
接下来,我们看下sysmon的里面具体做了些什么。
- 进入sysmon可以看到里面是一个死循环,这和我们上面提到的一样。该循环并非一直忙等,而是会根据系统的情况进行延时睡眠,初始的interval是20us,最大的interval是10ms。
- 在某些特殊的情况,sysmon可以进入更长时间(超过10ms)的睡眠,条件包括:
- 系统不需要schedtrace。看起来是和调度相关观测的内容,如果需要schedtrace,则sysmon需要及时输出相关数据;
- 系统处于停滞状态。这个停滞是我自己描述的,不一定准确,包括两种情况:1. 所有的p都是空闲的,此时系统中没有任务执行;2. 系统在等待进入gc状态,马上要stop the world;
满足上面两个条件,则可最大进行1min的睡眠。1min是最大强制gc时间(2min)的一半。
- sysmon的活跃状态,首先会坚持netpoll是否超过10ms没有被检查过,这是为了防止netpoll挂载goroutine的饥饿;
- 然后会进行retake操作,retake的内容就是对所有p进行检查,查看p是否处于syscall或者被一个goroutine占据时间过长(超过10ms),如果有则进行相应的处理;
- 最后还会进行gc和schedtrace相关的操作;
// src/runtime.go 5134
func sysmon() {lock(&sched.lock)sched.nmsys++checkdead()unlock(&sched.lock)lasttrace := int64(0)idle := 0 // how many cycles in succession we had not wokeup somebodydelay := uint32(0)for {if idle == 0 { // start with 20us sleep...delay = 20} else if idle > 50 { // start doubling the sleep after 1ms...delay *= 2}if delay > 10*1000 { // up to 10msdelay = 10 * 1000}usleep(delay)now := nanotime()if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs)) {lock(&sched.lock)if atomic.Load(&sched.gcwaiting) != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs) {syscallWake := falsenext := timeSleepUntil()if next > now {atomic.Store(&sched.sysmonwait, 1)unlock(&sched.lock)// Make wake-up period small enough// for the sampling to be correct.sleep := forcegcperiod / 2if next-now < sleep {sleep = next - now}shouldRelax := sleep >= osRelaxMinNSif shouldRelax {osRelax(true)}syscallWake = notetsleep(&sched.sysmonnote, sleep)if shouldRelax {osRelax(false)}lock(&sched.lock)atomic.Store(&sched.sysmonwait, 0)noteclear(&sched.sysmonnote)}if syscallWake {idle = 0delay = 20}}unlock(&sched.lock)}lock(&sched.sysmonlock)// Update now in case we blocked on sysmonnote or spent a long time// blocked on schedlock or sysmonlock above.now = nanotime()// trigger libc interceptors if neededif *cgo_yield != nil {...}// poll network if not polled for more than 10mslastpoll := int64(atomic.Load64(&sched.lastpoll))if netpollinited() && lastpoll != 0 && lastpoll+10*1000*1000 < now {atomic.Cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))list := netpoll(0) // non-blocking - returns list of goroutinesif !list.empty() {incidlelocked(-1)injectglist(&list)incidlelocked(1)}}if GOOS == "netbsd" && needSysmonWorkaround {...}if scavenger.sysmonWake.Load() != 0 {// Kick the scavenger awake if someone requested it.scavenger.wake()}// retake P's blocked in syscalls// and preempt long running G'sif retake(now) != 0 {idle = 0} else {idle++}// check if we need to force a GCif t := (gcTrigger{kind: gcTriggerTime, now: now}); t.test() && atomic.Load(&forcegc.idle) != 0 {lock(&forcegc.lock)forcegc.idle = 0var list gListlist.push(forcegc.g)injectglist(&list)unlock(&forcegc.lock)}if debug.schedtrace > 0 && lasttrace+int64(debug.schedtrace)*1000000 <= now {lasttrace = nowschedtrace(debug.scheddetail > 0)}unlock(&sched.sysmonlock)}
}
retake的操作也相对比较好理解。在p的介绍中我们提到过schedtick、syscalltick、sysmontick三个字段,其作用正是为了sysmon的检查。
sysmontick表示sysmon观测到的调度和系统调用情况,schedtick、syscalltick为实际的调度和系统调用情况。因为sysmon会经常睡眠,所以两者之间会有差异。
- sysmon在检查所有p的过程中,如果发现sysmontick落后于实际情况,就会以实际情况为准更新sysmontick,同时也不会再做校验。因为sysmon睡眠最大时间为10ms,说明对应的p在10ms内做了调度。
- 如果sysmontick和实际情况一只,则要看p是否运行一个goroutine超过10ms,如果是,则对m发送信号,触发异步抢占调度;如果p处于syscall状态超过10ms,则将p的持有权释放执行其他g。
func retake(now int64) uint32 {n := 0// Prevent allp slice changes. This lock will be completely// uncontended unless we're already stopping the world.lock(&allpLock)// We can't use a range loop over allp because we may// temporarily drop the allpLock. Hence, we need to re-fetch// allp each time around the loop.for i := 0; i < len(allp); i++ {_p_ := allp[i]if _p_ == nil {// This can happen if procresize has grown// allp but not yet created new Ps.continue}pd := &_p_.sysmonticks := _p_.statussysretake := falseif s == _Prunning || s == _Psyscall {// Preempt G if it's running for too long.t := int64(_p_.schedtick)if int64(pd.schedtick) != t {pd.schedtick = uint32(t)pd.schedwhen = now} else if pd.schedwhen+forcePreemptNS <= now {preemptone(_p_)// In case of syscall, preemptone() doesn't// work, because there is no M wired to P.sysretake = true}}if s == _Psyscall {// Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).t := int64(_p_.syscalltick)if !sysretake && int64(pd.syscalltick) != t {pd.syscalltick = uint32(t)pd.syscallwhen = nowcontinue}// On the one hand we don't want to retake Ps if there is no other work to do,// but on the other hand we want to retake them eventually// because they can prevent the sysmon thread from deep sleep.if runqempty(_p_) && atomic.Load(&sched.nmspinning)+atomic.Load(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {continue}// Drop allpLock so we can take sched.lock.unlock(&allpLock)// Need to decrement number of idle locked M's// (pretending that one more is running) before the CAS.// Otherwise the M from which we retake can exit the syscall,// increment nmidle and report deadlock.incidlelocked(-1)if atomic.Cas(&_p_.status, s, _Pidle) {if trace.enabled {traceGoSysBlock(_p_)traceProcStop(_p_)}n++_p_.syscalltick++handoffp(_p_)}incidlelocked(1)lock(&allpLock)}}unlock(&allpLock)return uint32(n)
}
相关文章:
【golang】调度系列之sysmon
调度系列 调度系列之goroutine 调度系列之m 调度系列之p 在golang的调度体系中,除了GMP本身,还有另外一个比较重要的角色sysmon。实际上,除了GMP和sysmon,runtime中还有一个全局的调度器对象。但该对象只是维护一些全局的数据&…...
货物寄到英国选择什么物流比较划算?
随着全球化的发展,越来越多的企业开始将产品销售到海外市场,其中英国作为一个重要的贸易伙伴,吸引了大量的中国企业的关注。然而,如何将货物安全、快速地运送到英国,成为了众多企业面临的一个问题。那么,货…...
vite + react 基本项目搭建
新建项目步骤略过 1、下载scss 无需任何配置就可以直接使用scss了 pnpm install sass使用scss配置全局颜色变量 新建/src/styles/variable.scss并在 $primary: #76aef9在vite.cinfig.js里配置 export default defineConfig({css: {preprocessorOptions: {scss: {javascrip…...
一个方法解决三道区间问题
1288. 删除被覆盖区间 56. 合并区间 986. 区间列表的交集 # 1288. 删除被覆盖区间 class Solution:def removeCoveredIntervals(self, intervals: List[List[int]]) -> int:# 按照起点升序排列,起点相同时,按照终点降序排列intervals.sort(key lamb…...
sub0 里斯本精彩回顾:探索波卡区块的创新空间
sub0 Europe 2023 已在葡萄牙里斯本圆满结束!sub0 大会是波卡生态开发者大会,由波卡协议的主要开发方 Parity Technologies 举办的开发者大会,汇聚了全球 Substrate 开发者和学习者,旨在为 Polkadot 和 Kusama 生态的开发者、贡献…...
颜色+情感的英语表达还有这些,零基础学英语口语去哪里,柯桥有推荐的吗?
当我们探讨关于"blue"(蓝色)的多义性时,我们会发现英语中有许多其他词汇也有类似的双关意义。 既可以表示一种颜色或物理属性,又可以代表一种情感或心理状态。 这种现象在语言中很常见,反映了语言的丰富性和…...
exoplayer的使用-6,播放器的选择
需要一个能播放蓝光的,高码率的播放器,在使用现成的播放器的基础上,可选的有几个,exoplayer,vlc,ijk,mpv. exoplayer的更新频繁,适应性强,扩展性一般,因为它基于系统的硬解,音频可扩展,使用ffmpeg可以解决. 有国际化支持,音频,字幕这些显示效果好. 对杜比视频,hdr这些支持看设…...
Windows上安装 Go 环境
一、下载go环境 下载go环境:Go下载官网链接找到自己想下载的版本,点击下载,比如我这是windows64位的,我就直接点击最新的。 二、安装go环境 双击下载的.msi文件 next next 他默认的是c盘,你自己可以改,然…...
【设计模式】四、工厂模式
文章目录 概述工厂模式简单工厂模式:工厂方法模式抽象工厂模式小结 概述工厂模式 传统方式: 简单工厂模式: 简单工厂模式的设计方案: 定义一个可以实例化 Pizaa 对象的类,封装创建对象的代码。 存在的问题: 简单工厂…...
十九,镜面IBL--BRDF积分贴图
再回顾下镜面部分的分割求和近似法 现在关注第二部分 最后可化为 也就是说,这两部分积分可以获得F0的系数和F0的偏差。 这两个值可以存储到BRDF积分贴图的RG部分。void main() { vec2 integratedBRDF IntegrateBRDF(TexCoords.x, TexCoords.y); FragColor …...
Linux 创建 终止线程(thread)
进程线程区别 创建线程 #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); -功能:创建一个子线程,一般情况下main函数所在的线程称为主线程,…...
【IPC 通信】信号处理接口 Signal API(6)
收发信号思想是 Linux 程序设计特性之一,一个信号可以认为是一种软中断,通过用来向进程通知异步事件。 本文讲述的 信号处理内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解信号编程。 kill(2) 遵循 POSIX.1 - 2008 1.库 …...
ipaguard界面概览
ipaguard界面概览 ipaguard界面分左右2块:左边菜单导航栏,右边的功能区 左侧菜单:按模块分成启动界面,代码模块,文件模块,重签名与测试模块 右侧主功能区会随着功能变化,但是整体分3块…...
萌新的FPGA学习绪论-1
萌新的FPGA学习绪论-1 其实很多的课和内容都是相通的 我在跑完单周期的RiscV时候 虽然最后还差点意思但是基本的逻辑实现没有特别大的问题 过两天写一个Spec文档说明一下 由于开始一个新的设计 所以对于RiscV的设计暂时放到一边希望我能在接下来的时间内尽快完成 暂时不说这个…...
目标检测算法改进系列之Backbone替换为EMO
EMO:结合 Attention 重新思考移动端小模型中的基本模块 近年来,由于存储和计算资源的限制,移动应用的需求不断增加,因此,本文的研究对象是端侧轻量级小模型 (参数量一般在 10M 以下)。在众多小模型的设计中࿰…...
Laravel一些优雅的写法
1. 新增操作 // 原则,所有服务类只有一个public入口,或者多个public入口,但是他们做都是同一件事情 Class CreateService {// 创建类的入口, 根据dto去新建public function create(Dto $dto){// 先构建model对象, 不要在事务期间构建,减少事务…...
vue+three.js中使用Ammo.js
直接通过npm i ammo.js安装进webpack的项目里调用时,会出现如下报错: ERROR in ./node_modules/ammo.js/ammo.js 1:1683-1696 Mo…...
【k8s】kubectl命令详解
文章目录 命令行工具 kubectl在slave下配置kubectl资源操作创建对象 API概述类型访问控制认证授权 废弃API说明 资源管理资源管理介绍资源管理方式命令式对象管理命令式对象配置创建yaml文件创建资源查看资源删除资源 声明式对象配置 kebectl在node节点上运行查看每种资源的可配…...
Centos 7 部署SVN服务器
一、安装SVN 1、安装Subversion sudo yum -y install subversion2、验证是否安装成功(查看svn版本号) svnserve --version二、创建版本库 1、先建立目录,目录位置可修改 mkdir -p /var/svn cd /var/svn2、创建版本库,添加权限…...
SEO方案尝试--Nuxtjs项目基础配置
Nuxtjs 最新版 Nuxt3 项目配置 安装nuxtjs 最新版 Nuxt3 参考官网安装安装插件安装ElementPlus页面怎么跳转,路由怎么实现404页面该怎么配置配置 网页的title 安装nuxtjs 最新版 Nuxt3 参考官网安装 安装插件 安装ElementPlus 安装 Element Plus 和图标库 # 首先&…...
【算法分析与设计】动态规划(上)
目录 一、学习要点二、算法总体思想三、动态规划基本步骤四、矩阵连乘问题4.1 完全加括号的矩阵连乘积4.2 穷举法4.3 动态规划4.3.1 分析最优解的结构4.3.2 建立递归关系4.3.3 计算最优值4.3.4 用动态规划法求最优解 五、动态规划算法的基本要素5.1 最优子结构5.2 重叠子问题5.…...
Java多线程篇(6)——AQS之ReentrantLock
文章目录 1、管程2、AQS3、ReentrantLock3.1、lock/unlock3.1.1、lock3.1.2、unlock 3.2、一些思考 1、管程 什么是管程? 管理协调多个线程对共享资源的访问,是一种高级的同步机制。 有哪些管程模型? hansen:唤醒其他线程的代码…...
【计算机网络】IP协议第二讲(Mac帧、IP地址、碰撞检测、ARP协议介绍)
IP协议第二讲 1.IP和Mac帧2.碰撞检测2.1介绍2.2如何减少碰撞发生2.3MTU2.4一些补充 3.ARP协议3.1协议介绍3.2报文格式分析 1.IP和Mac帧 IP(Internet Protocol)和MAC(Media Access Control)帧是计算机网络中两个不同层次的概念&am…...
TouchGFX界面开发 | 按钮控件应用示例
按钮控件应用示例 按钮是最常见的部件之一,有了按钮就可以点击,从而响应事件,达到人机交互的目的。TouchGFX Designer内置了七种按钮部件: 下压按钮:能够在被释放时发送回调,按下和释放状态都关联了图像标…...
BSVD论文理解:Real-time Streaming Video Denoising with Bidirectional Buffers
BSVD是来自香港科技大学的一篇比较新的视频去噪论文,经实践,去噪效果不错,在这里分享一下对这篇论文的理解。 论文地址:https://arxiv.org/abs/2207.06937 代码地址:GitHub - ChenyangQiQi/BSVD: [ACM MM 2022] Real…...
共同见证丨酷雷曼武汉运营中心成立2周年
酷雷曼武汉运营中心2周年 全国合作商齐贺武汉公司2周年庆 2021年 作为酷雷曼辐射全国版图的又一重要据点 酷雷曼武汉运营中心 在“中国光谷”正式成立 沉浸式参观酷雷曼武汉公司 2年时间 尽管历经诸多客观因素的挑战 但后浪扬帆,依然交出了不斐的成绩 解决…...
一种单键开关机电路图
我们设计产品时,通常需要设计单键开关机功能。 单键开关机,通常需要单片机的两个IO完成,一个IO用于保持开机状态。另外,一个IO用于判定关机状态。 下面就是一种单键开关机电路原理图: 此单键开关电路已经在S2W-M02、S2…...
设计模式2、抽象工厂模式 Abstract Factory
解释说明:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。 简言之,一个工厂可以提供创建多种相关产品的接口,而无需像工厂方法一样,为每一个产品都提供一个具体工厂 抽象工厂(Abstra…...
C++ 32盏灯,利用进制和 与 或 进行设计
一共32盏灯,设计一个灯光控制系统,其中 台球部8盏灯 桌游区8盏灯 酒吧区8盏灯 休息区8盏灯 满足以下功能 1、能够独立控制每一盏灯 2、能够一次性打开或关闭一个区域的全部灯光 3、能够获取各个区域的灯光打开关闭情况 4、能够一次性关闭打开的灯&#x…...
Ffmpeg-(1)-安装:ubuntu系统安装Ffmpeg应用
1、下载源码压缩包 https://ffmpeg.org/download.html 点击Download Source Code下载即可 解压: tar -xvjf ffmpeg-snapshot.tar.bz2 得到:ffmpeg目录 cd ffmpeg 或者:直接下 wget http://www.ffmpeg.org/releases/ffmpeg-5.1.tar.gztar -zx…...
做调查问卷赚钱的网站/关键词优化排名网站
亲测可用,若有疑问请私信 一、设置导航栏颜色 在url后面拼接dd_nav_bgcolor参数即可,如下: 支持的格式:“AARRGGBB” http://abc.xyz?dd_nav_bgcolorFF5E97F6 二、微应用页面支持横屏 在url后面拼接dd_orientation参数即可,如…...
做网站采集内容/杭州网站seo外包
#!/bin/bash echo "wxc_dump.sh is running!" #抓包600秒保存一个包以时间命名 tcpdump -i ens160 -s0 -G 600 -Z root -w ./%Y%m%d_%H%M%S.pcap & #while条件括号里面不能少两个空格 #find当前路径所有后缀.pcap,文件内容最后修改时间比当前大于120分…...
衢州建设公司网站/小红书代运营
心情良好转载于:https://www.cnblogs.com/qq3111901846/p/6178722.html...
怎么做建设网站首页/html家乡网站设计
征途手机版主推国战系统,其中国家刺探是什么呢?国战相关的问题有哪些呢?今天当乐网小编给大家带来相关内容的解答:Q:《征途》共有几个国家?A:10个国家,分别是吴、赵、越、楚、燕、唐…...
如何修改网站logo/百度推广做二级域名
每天花1-2个小时左右来学习就够了。 PMP考试其实说难也不难,说容易也不简单,但只要你是认真的在学,基本上都能过。主要还是看上课的老师讲课、是否专业,这些方面。 今天就跟大家讲讲一个完全不了解PMP的人要怎样去准备PMP考试&a…...
国贸做网站公司/如何制作网站
今天,说一Ipad充不了电,我想才没买好久,这么快电池就坏了呀。难道买到歪货了? 它的表现是充电线一接上去,电池指示有反应,也有"闪电"标志,就是充不进去电。本来想打客服的,…...