前言
Swoole
内核团队开设的专栏,会逐渐投入精力写文章介绍Swoole
的开发历程,实现原理,应用实践等,大家可以更好的交流,共同学习,建设PHP
生态。
协程调度
去年Swoole
推出了4.0
版本后,完整的支持PHP
协程,我们可以基于协程实现CSP
编程,身边的开发者惊呼,原来PHP代码还可以这样写。Swoole
的协程默认是基于IO调度,程序中有阻塞会自动让出当前协程,协程的各种优势我们不在这里展开讨论。如果是IO
密集型的场景,可以表现得很不错。但是对于CPU
密集型的场景,会导致一些协程因为得不到CPU
时间片被饿死。
抢占式调度
我们在今年年初就计划实现Swoole
的抢占式调度,以满足实现有些场景下的不均衡调度带来的问题。我们中间经历了几个版本,在这里和大家分享一下开发过程中的动机和解决办法。
我们目的是为了均衡调度每个协程的CPU
时间,比如协程3需要比较长的执行时间,我们必须把协程3的CPU
时间主动中断,而不依赖IO
事件,使得每个协程得到平均的执行时间。
起初,我们的想法是可以从PHP
的循环中自动检测执行实践,若达到限制,可以自动让出当前协程。因为毕竟很少有人一马平川的写出占用很多CPU
的代码,大都通过循环条件来控制。我们hook
循环指令,每次执行循环指令的时候,都来检查协程的执行时间,我们很欣喜的得到了最初的版本。但是这样做比较hack,而且opcode
经过opcache
优化后,情况会变得有些复杂。
后来我们使用PHP
的ticks
机制,也就是在PHP
代码编译期间,注入ticks
指令,可以执行相应的函数,我们可以在这些函数中检测处理协程的时间,达到抢占式的效果,但是这里有一个问题,PHP
的declare(ticks=N)
语法,只对当前脚本范围有效,也就是说项目稍微大点,require
或者include
进来的脚本,并不会自动注入ticks
指令,这样Swoole
开发者几乎是无法接受的。我们也试图给PHP
官方提一个PR,可以在扩展层设置一个全局默认的ticks
,但是官方不愿意采纳我们的提交,因为官方觉得这个功能对性能损耗比较大,而且有可能在PHP8
移除这个功能。其实经过实测这个性能损耗并不大,而且我们已经在生产环境验证,并取得了显著的效果,即可以让出某些CPU
密集的逻辑部分,使得服务整个相应时间更加均衡。
下图是我们生产环境一个RPC接口的调用端统计数据对比,客户端等待超时时间为2s,超时则统计为错误。
左边一侧是没有抢占式调度,右侧是开了抢占式调度,可以发现,左侧总是会有偶尔超时情况,而经过优化之后,没有一个超时的请求,请求响应时间非常平滑,提升了服务的稳定性。
可以从上图看出,由于抢占式调度的加入,去除了请求耗时高的毛刺,使得平均请求时间变得更加平滑,稳定。
想要做抢占式调度,对于PHP
来说,有两个途径
- 单线程的
PHP
的执行流,通过执行指令做文章,可以在PHP
执行流程中注入逻辑,以检查执行时间,再加上Swoole
的协程能力,可以在不同的协程中切换,以达到抢占CPU
的目的。 - 考虑开线程,负责检查当前执行协程执行时间。
经过以上办法的尝试,注入指令的路数基本是无法得到官方的支持,我们只能另谋出路,多开一个线程,只负责检查当前协程。具体的做法是,利用PHP-7.1.0
引入的VM interrupt
机制,默认每隔5ms检查一下当前协程是否达到最大执行时间,默认为10ms,如果超过,则让出当前协程,达到被其他协程抢占的目的。
示例代码
需要Swoole 4.4
或更高版本
<"start\n"; $flag = 1; go(function () use (&$flag) { echo "coro 1 start to loop\n"; $i = 0; for (;;) { if (!$flag) { break; } $i++; } echo "coro 1 can exit\n"; }); $end = microtime(1); $msec = ($end - $start) * 1000; echo "use time $msec\n"; go(function () use (&$flag) { echo "coro 2 set flag = false\n"; $flag = false; }); echo "end\n";
执行结果
start coro 1 start to loop use time 11.121988296509 coro 2 set flag = false end coro 1 can exit
可以发现,代码逻辑可以从第一个协程的死循环中自动yield
出来,执行第二个协程,如果没有这个特性,第二个协程永远不会被执行,导致被饿死。而这样做,第二个协程可以顺利被执行,最后执行结束后,第一个协程也会接着继续往下执行。达到我们的第二个协程主动抢占第一个协程CPU
的效果。
这个特性在生产环境非常有用,尤其是对于实时系统或者响应时间比较敏感的场景。
最后
感谢大家对 Swoole 的长期支持和关注。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
Swoole,协程抢占式调度器
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】