首发于 1412的架构鶸文

epoll与Communicator系列笔记(2) 系统调度性能优化神器sched_yield()

本系列是鶸鶸的我对网络相关知识的梳理,如有疏漏欢迎各位大神指出,也希望能够抛砖引玉帮助到有需要的小伙伴。

第一篇知乎站内链接:
1412:epoll与Communicator系列笔记(1) epoll_wait()参数timeout相关的源码阅读笔记

本篇原文于2021年2月底发在架构鶸的公众号上,仅为方便懒得点开知乎看的胖友们:
epoll与Communicator系列笔记(2) 系统调度性能优化神器sched_yield()

1. epoll相关的两点优化

上一篇说到,学到一些神奇的做法后,我也对rpc尝试了一些epoll层面的优化。优秀的字节小伙伴实现Go下的RPC,分享出的是两个优化点:

  1. 不同情况下使用不同的timeout,可以利用到epoll_wait()内部的实现而减少不必要的代码调用:如果这次可以取到东西,则下次设置timeout为0继续拿;这次取不到则设置-1
  2. 在timeout设置为-1的时候,主动切换当前协程以提速;

第1点我上篇文章已经实践过,因为C++与Go下的epoll实现不同。而linux内核对epoll_wait()的实现,是上来就是为我们拿已经ready的事件,也就是说只要有事件,timeout设置多少并不额外影响性能。

对于第2点,其实我也有尝试>///< 在谢爷的指导下,C++下对应的做法,就是利用sched_yield()切出当前线程,这个改进简直效果拔群,不明觉厉!!!

所以,虽然最近忙成狗勾,但这篇还是想尽快简单记录一下~

2. 如何使用sched_yield()

这里列一下epoll的基本使用方式,外加上述提到的两点改进。

其中第二点,就是如果当前拿不到事件,我会主动调用sched_yield()让出线程,等下次我被调起时再做下一轮wait~

其实workflow里对epoll的使用会更复杂

因为我们对用户的TimerTask的实现,是借用了timerfd去做的。因此,每次操作epoll_wait()之前,还要根据用户所有的TimerTask,去维护一下当前的timerfd

但本次就不细说了,毕竟我不懂→_→ 以上就是测试代码的简化版了~

3. 实验测试结果

这里先说明一下,为什么会有4次实验。因为我按上述代码改动:发现性能竟然有5%的提升!!!

各位同学,网络框架底层的5%!!!那是相当珍贵!相当感人!

我把这个结果发给谢爷,谢爷高冷地来一句:“你要单独测一下sched_yield()”

于是此实验有两个变量

果不其然,仅仅修改timeout其实并没有任何收益,而加入sched_yield()才是提升关键,但同时也会引起更多的cpu占用

其他实验说明也在表里,不再赘述,如有疏漏欢迎指正~

4. 鶸鶸的分析

这里man一下sched_yield()

sched_yield() causes the calling thread to relinquish the CPU. The thread is moved to the end of the queue for its static priority and a new thread gets to run.

就会发现,其实看完也是一脸懵逼~~Q_Q~~ 于是我就网上查了下,内核有个东西叫做完全公平调度器,大概能够帮助我分析这个现象。

首先,cpu对于一个线程怎么调度,是取决于:

linux的调度器CFS,会根据这两个值来决定你当前被放到哪个队列。它内部管理了三个队列:

  1. 等待队列
  2. 运行队列
  3. 过期队列

为什么要有三个队列呢?这里的等待队列,不是单纯地等待执行,而是那些休眠阻塞的线程。而如果你这个优先级也不是很高,还被执行了超级久超过你的咖位,那你就会被扔到第三个队列-过期队列里。

我们如果用sched_yield()切出,就是主动放到过期队列里,等其他人都享受够了他们deserve的时间,才会开始调度这个过期队列。

这么一听,感觉不合理啊!这明明是个牺牲小我、完成大我,让系统减少忙等的函数而已,而我们这里用epoll明明就不是空跑!

但其实仔细想想,如果我们不主动切出的话,下一次进入epoll_wait()的时候,就会因为-1、且没事件,而被扔进epoll的等待,我们上次看过,epoll内部会先进行nonblockigloop检查,然后扔进自己的ep->wq里,然后再由操作系统切出

这一系列的骚操作,都可以通过提前切出而避免。一般来说,等下一次再轮到我的时候,epoll的事件都已经准备好了~这些操作都不需要了。毕竟epoll_wait()在进行挂起前,都会认真地再检查一次是否真的没有事件,上次看还不太明白为什么要这样做,现在能够理解了,是因为真正被挂起的代价太高。

另外一点小猜测是,CFS对于一个线程切出来之后,应该放到哪个队列,还得算一算,这也是xue微有点消耗的?如果我们能够明知道要等的情况,比如:重负载而当前资源没到位,确实完全可以主动告诉操作系统,减少操作系统做决策的负担。

5. 其他._.

这么一想,操作系统还是非常开明的,制订好机制,给你做策略的权利。当然也正如man所说,sched_yield()的调用得非常慎重,稍微用得不好,往往会降低性能。

而workflow也没有引入这点改动。因为5%的吞吐提升,只有在epoll线程繁重的时候才能体现。而一个完备健壮的系统要考虑的,更多是改动点的合理性通用性。而这个改动,不说多make sense,至少非常不通用。更何况,我狗线上机器负载已经够高了,引入这点改动还要增加cpu占用,实在得不偿失,不值得做这么tricky的事情。

我鶸鶸地经历了这么些优化后,发现一个事情:越是漂亮、通用、简洁的做法,往往也是被时间证明为正确的做法。计算机的世界里有它所相信的美~

以上就是我的尝试和分析~目前如果工作涉及到网络相关,感觉自己还是摸着石头过河。但是年后这几天真是忙到质壁分离,事情已经密密麻麻排到下个月了。blog的话,且写且珍惜吧 ~希望下一篇写出来的时候,我可以有更organized的理解(冲鸭~~

代做工资流水公司常德个人流水公司济南代办背调工资流水宿迁打印企业流水打印东莞企业对私流水样本襄阳薪资流水单模板长春打印工资银行流水邯郸办企业流水打印郑州企业银行流水办理泰安入职工资流水价格咸阳做车贷流水海口代开工资流水无锡车贷流水代开台州企业贷流水打印舟山办理个人工资流水阜阳背调工资流水办理黄冈打工资流水app截图南阳打签证工资流水黄冈房贷流水菏泽个人流水多少钱邯郸自存流水图片大庆个人银行流水费用重庆转账银行流水代办嘉兴个人流水代做台州对公流水制作唐山个人工资流水 公司滁州做银行流水邯郸查工资代付流水惠州贷款流水费用嘉兴代办银行流水账单开封工资流水报价香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

代做工资流水公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化