摘要:搶占式調(diào)度我們在今年年初就計劃實現(xiàn)的搶占式調(diào)度,以滿足實現(xiàn)有些場景下的不均衡調(diào)度帶來的問題??紤]開線程,負(fù)責(zé)檢查當(dāng)前執(zhí)行協(xié)程執(zhí)行時間。達到我們的第二個協(xié)程主動搶占第一個協(xié)程的效果。
前言
Swoole內(nèi)核團隊開設(shè)的專欄,會逐漸投入精力寫文章介紹Swoole的開發(fā)歷程,實現(xiàn)原理,應(yīng)用實踐等,大家可以更好的交流,共同學(xué)習(xí),建設(shè)PHP生態(tài)。
協(xié)程調(diào)度去年Swoole推出了4.0版本后,完整的支持PHP協(xié)程,我們可以基于協(xié)程實現(xiàn)CSP編程,身邊的開發(fā)者驚呼,原來PHP代碼還可以這樣寫。Swoole的協(xié)程默認(rèn)是基于IO調(diào)度,程序中有阻塞會自動讓出當(dāng)前協(xié)程,協(xié)程的各種優(yōu)勢我們不在這里展開討論。如果是IO密集型的場景,可以表現(xiàn)得很不錯。但是對于CPU密集型的場景,會導(dǎo)致一些協(xié)程因為得不到CPU時間片被餓死。
搶占式調(diào)度我們在今年年初就計劃實現(xiàn)Swoole的搶占式調(diào)度,以滿足實現(xiàn)有些場景下的不均衡調(diào)度帶來的問題。我們中間經(jīng)歷了幾個版本,在這里和大家分享一下開發(fā)過程中的動機和解決辦法。
我們目的是為了均衡調(diào)度每個協(xié)程的CPU時間,比如協(xié)程3需要比較長的執(zhí)行時間,我們必須把協(xié)程3的CPU時間主動中斷,而不依賴IO事件,使得每個協(xié)程得到平均的執(zhí)行時間。
起初,我們的想法是可以從PHP的循環(huán)中自動檢測執(zhí)行實踐,若達到限制,可以自動讓出當(dāng)前協(xié)程。因為畢竟很少有人一馬平川的寫出占用很多CPU的代碼,大都通過循環(huán)條件來控制。我們hook循環(huán)指令,每次執(zhí)行循環(huán)指令的時候,都來檢查協(xié)程的執(zhí)行時間,我們很欣喜的得到了最初的版本。但是這樣做比較hack,而且opcode經(jīng)過opcache優(yōu)化后,情況會變得有些復(fù)雜。
后來我們使用PHP的ticks機制,也就是在PHP代碼編譯期間,注入ticks指令,可以執(zhí)行相應(yīng)的函數(shù),我們可以在這些函數(shù)中檢測處理協(xié)程的時間,達到搶占式的效果,但是這里有一個問題,PHP的declare(ticks=N)語法,只對當(dāng)前腳本范圍有效,也就是說項目稍微大點,require或者include進來的腳本,并不會自動注入ticks指令,這樣Swoole開發(fā)者幾乎是無法接受的。我們也試圖給PHP官方提一個PR,可以在擴展層設(shè)置一個全局默認(rèn)的ticks,但是官方不愿意采納我們的提交,因為官方覺得這個功能對性能損耗比較大,而且有可能在PHP8移除這個功能。其實經(jīng)過實測這個性能損耗并不大,而且我們已經(jīng)在生產(chǎn)環(huán)境驗證,并取得了顯著的效果,即可以讓出某些CPU密集的邏輯部分,使得服務(wù)整個相應(yīng)時間更加均衡。
下圖是我們生產(chǎn)環(huán)境一個RPC接口的調(diào)用端統(tǒng)計數(shù)據(jù)對比,客戶端等待超時時間為2s,超時則統(tǒng)計為錯誤。
左邊一側(cè)是沒有搶占式調(diào)度,右側(cè)是開了搶占式調(diào)度,可以發(fā)現(xiàn),左側(cè)總是會有偶爾超時情況,而經(jīng)過優(yōu)化之后,沒有一個超時的請求,請求響應(yīng)時間非常平滑,提升了服務(wù)的穩(wěn)定性。
可以從上圖看出,由于搶占式調(diào)度的加入,去除了請求耗時高的毛刺,使得平均請求時間變得更加平滑,穩(wěn)定。
想要做搶占式調(diào)度,對于PHP來說,有兩個途徑
單線程的PHP的執(zhí)行流,通過執(zhí)行指令做文章,可以在PHP執(zhí)行流程中注入邏輯,以檢查執(zhí)行時間,再加上Swoole的協(xié)程能力,可以在不同的協(xié)程中切換,以達到搶占CPU的目的。
考慮開線程,負(fù)責(zé)檢查當(dāng)前執(zhí)行協(xié)程執(zhí)行時間。
經(jīng)過以上辦法的嘗試,注入指令的路數(shù)基本是無法得到官方的支持,我們只能另謀出路,多開一個線程,只負(fù)責(zé)檢查當(dāng)前協(xié)程。具體的做法是,利用PHP-7.1.0引入的VM interrupt機制,默認(rèn)每隔5ms檢查一下當(dāng)前協(xié)程是否達到最大執(zhí)行時間,默認(rèn)為10ms,如果超過,則讓出當(dāng)前協(xié)程,達到被其他協(xié)程搶占的目的。
示例代碼需要Swoole 4.4或更高版本
執(zhí)行結(jié)果start coro 1 start to loop use time 11.121988296509 coro 2 set flag = false end coro 1 can exit可以發(fā)現(xiàn),代碼邏輯可以從第一個協(xié)程的死循環(huán)中自動yield出來,執(zhí)行第二個協(xié)程,如果沒有這個特性,第二個協(xié)程永遠不會被執(zhí)行,導(dǎo)致被餓死。而這樣做,第二個協(xié)程可以順利被執(zhí)行,最后執(zhí)行結(jié)束后,第一個協(xié)程也會接著繼續(xù)往下執(zhí)行。達到我們的第二個協(xié)程主動搶占第一個協(xié)程CPU的效果。
這個特性在生產(chǎn)環(huán)境非常有用,尤其是對于實時系統(tǒng)或者響應(yīng)時間比較敏感的場景。
最后感謝大家對 Swoole 的長期支持和關(guān)注。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/31532.html
摘要:協(xié)程完全有用戶態(tài)程序控制,所以也被成為用戶態(tài)的線程。目前支持協(xié)程的語言有很多,例如等。協(xié)程之旅前篇結(jié)束,下一篇文章我們將深入分析原生協(xié)程部分的實現(xiàn)。 寫在最前 ??Swoole協(xié)程經(jīng)歷了幾個里程碑,我們需要在前進的道路上不斷總結(jié)與回顧自己的發(fā)展歷程,正所謂溫故而知新,本系列文章將分為協(xié)程之旅前、中、后三篇。 前篇主要介紹協(xié)程的概念和Swoole幾個版本協(xié)程實現(xiàn)的主要方案技術(shù); 中篇主...
摘要:本文先回顧生成器,然后過渡到協(xié)程編程。其作用主要體現(xiàn)在三個方面數(shù)據(jù)生成生產(chǎn)者,通過返回數(shù)據(jù)數(shù)據(jù)消費消費者,消費傳來的數(shù)據(jù)實現(xiàn)協(xié)程。解決回調(diào)地獄的方式主要有兩種和協(xié)程。重點應(yīng)當(dāng)關(guān)注控制權(quán)轉(zhuǎn)讓的時機,以及協(xié)程的運作方式。 轉(zhuǎn)載請注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎(chǔ) web請求 cookie web響應(yīng) sess...
摘要:如果僅依靠程序自動交出控制的話,那么一些惡意程序?qū)苋菀渍加萌繒r間而不與其他任務(wù)共享。多個操作可以在重疊的時間段內(nèi)進行。 PHP下的異步嘗試系列 如果你還不太了解PHP下的生成器,你可以根據(jù)下面目錄翻閱 PHP下的異步嘗試一:初識生成器 PHP下的異步嘗試二:初識協(xié)程 PHP下的異步嘗試三:協(xié)程的PHP版thunkify自動執(zhí)行器 PHP下的異步嘗試四:PHP版的Promise ...
摘要:概述本系列文章將從開發(fā)者角度梳理開發(fā)實時聯(lián)網(wǎng)游戲后臺服務(wù)過程中可能面臨的挑戰(zhàn),并針對性地提供相應(yīng)解決思路,期望幫助開發(fā)者依據(jù)自身游戲特點做出合理的技術(shù)選型。多路復(fù)用避免了讀寫阻塞,減少了上下文切換,提升了利用率和系統(tǒng)吞吐率。 概述:本系列文章將從開發(fā)者角度梳理開發(fā)實時聯(lián)網(wǎng)游戲后臺服務(wù)過程中可能面臨的挑戰(zhàn),并針對性地提供相應(yīng)解決思路,期望幫助開發(fā)者依據(jù)自身游戲特點做出合理的技術(shù)選型。 關(guān)...
閱讀 1211·2021-11-24 10:43
閱讀 3235·2021-11-22 09:34
閱讀 3610·2021-10-08 10:04
閱讀 4011·2021-09-23 11:58
閱讀 3166·2019-08-30 15:44
閱讀 543·2019-08-30 13:01
閱讀 1231·2019-08-28 18:07
閱讀 1502·2019-08-26 13:42