摘要:協程完全有用戶態程序控制,所以也被成為用戶態的線程。目前支持協程的語言有很多,例如等。協程之旅前篇結束,下一篇文章我們將深入分析原生協程部分的實現。
寫在最前
??Swoole協程經歷了幾個里程碑,我們需要在前進的道路上不斷總結與回顧自己的發展歷程,正所謂溫故而知新,本系列文章將分為協程之旅前、中、后三篇。
前篇主要介紹協程的概念和Swoole幾個版本協程實現的主要方案技術;
中篇主要深入Zend分析PHP部分的原理和實現;
后篇主要補充和分析協程4.x的實現。
軟文正式開始 協程是什么???概念其實很早就出現了,摘wiki一段:According to Donald Knuth, the term coroutine was coined by Melvin Conway in 1958, after he applied it to construction of an assembly program.The first published explanation of the coroutine appeared later, in 1963. 協程要比c語言的歷史還要悠久,究其概念,協程是子程序的一種, 可以通過yield的方式轉移程序控制權,協程之間不是調用者與被調用者的關系,而是彼此對稱、平等的。協程完全有用戶態程序控制,所以也被成為用戶態的線程。協程由用戶以非搶占的方式調度,而不是操作系統。正因為如此,沒有系統調度上下文切換的開銷,協程有了輕量,高效,快速等特點。(大部分為非搶占式,但是,比如golang在1.4也加入了搶占式調度,其中一個協程發生死循環,不至于其他協程被餓死。需要在必要的時刻讓出CPU,Swoole在V4.3.2增加了這個特性)。
??協程近幾年如此火爆,很大一部分原因歸功與golang在中國的流行和快速發展,受到很多開發的喜愛。目前支持協程的語言有很多,例如: golang、lua、python、c#、javascript等。大家也可以用很短的代碼用c/c++擼出協程的模型。當然PHP也有自己的協程實現,也就是生成器,我們這里不展開討論。
Swoole1.x?? Swoole最初以高性能網絡通訊引擎的姿態進入大家視線,Swoole1.x的編碼主要是異步回調的方式,雖然性能非常高效,但很多開發都會發現,隨著項目工程的復雜程度增加,以異步回調的方式寫業務代碼是和人類正常思維相悖的,尤其是回調嵌套多層的時候,不僅開發維護成本指數級上升,而且出錯的幾率也大幅增加。大家理想的編碼方式是:同步編碼得到異步非阻塞的性能。所以Swoole很早的時候就開始了協程的探索。
??最初的協程版本是基于PHP生成器GeneratorsYield的方式實現的,可以參考PHP大神Nikita的早期博客的關于協程介紹。PHP和Swoole的事件驅動的結合可以參考騰訊出團隊開源的TSF框架,我們也在很多生產項目中使用了該框架,確實讓大家感受到了,以同步編程的方式寫異步代碼的快感,然而,現實總是很殘酷,這種方式有幾個致命的缺點:
所有主動讓出的邏輯都需要yield關鍵字。這會給程序員帶來極大的概率犯錯,導致大家對協程的理解轉移到了對Generators語法的原理的理解。
由于語法無法兼容老的項目,改造老的項目工程復雜度巨大,成本太高。
這樣使得無論新老項目,使用都無法得心應手。
Swoole2.x?? 2.x之后的協程都是基于內核原生的協程,無需yield關鍵字。2.0的版本是一個非常重要的里程碑,實現了php的棧管理,深入zend內核在協程創建,切換以及結束的時候操作PHP棧。在Swoole的文檔中也介紹了很多關于每個版本實現的細節,我們這篇文章只對每個版本的協程驅動技術做簡單介紹。原生協程都有對php棧的管理,后續我們會多帶帶拿一片文章來深入分析PHP棧的管理和切換。
?? 2.x主要使用了setjmp/longjmp的方式實現協程,很多C項目主要采用這種方式實現try-catch-finally,大家也可以參考Zend內核的用法。setjmp的首次調用返回值是0,longjmp跳轉時,setjmp的返回值是傳給longjmp的value。 setjmp/longjmp由于只有控制流跳轉的能力。雖然可以還原PC和棧指針,但是無法還原棧幀,因此會出現很多問題。比如longjmp的時候,setjmp的作用域已經退出,當時的棧幀已經銷毀。這時就會出現未定義行為。假設有這樣一個調用鏈:
func0() -> func1() -> ... -> funcN()
只有在func{i}()中setjmp,在func{i+k}()中longjmp的情況下,程序的行為才是可預期的。
Swoole3.x3.x是生命周期很短的一個版本,主要借鑒了fiber-ext項目,使用了PHP7的VM interrupts機制,該機制可以在vm中設置標記位,在執行一些指令的時候(例如:跳轉和函數調用等)檢查標記位,如果命中就可以執行相應的hook函數來切換vm的棧,進而實現協程。雖然我們完整的實現了協程的功能,但是由于并沒有相對2.x有很大的進步,原因我們后續的文章會做進一步分析,所以我們放棄了這個版本,直接進入了4.x的版本迭代。
Swoole4.x4.x協程是當前Swoole的協程版本,借鑒了前面版本的缺點和問題,引入了PHP+C雙棧管理維護,完美的支持PHP各種語法,詳細分析我們放在系列文章最后。
End協程之旅前篇結束,下一篇文章我們將深入Zend分析Swoole原生協程PHP部分的實現。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/31278.html
摘要:在中的應用官網源碼解讀號外號外歡迎大家我們開發組定了一個就線下聚一次的小目標上一篇源碼解讀反響還不錯不少同學推薦再加一篇講解一下中使用到的功能幫助大家開啟的實戰之旅服務器開發涉及到的相關技術領域的知識非常多不日積月累打好基礎是很難真正 date: 2017-12-14 21:34:51title: swoole 在 swoft 中的應用 swoft 官網: https://www.sw...
摘要:搶占式調度我們在今年年初就計劃實現的搶占式調度,以滿足實現有些場景下的不均衡調度帶來的問題。考慮開線程,負責檢查當前執行協程執行時間。達到我們的第二個協程主動搶占第一個協程的效果。 前言 Swoole內核團隊開設的專欄,會逐漸投入精力寫文章介紹Swoole的開發歷程,實現原理,應用實踐等,大家可以更好的交流,共同學習,建設PHP生態。 協程調度 去年Swoole推出了4.0版本后,完整...
摘要:初識協程執行結果協程與同步模式比較我們一直在說協程適合用于密集場景,在同樣的硬件配置環境下,它會比傳統的同步模式承載更多的訪問量。假設一次查詢為,在傳統同步模式下,當前進程在這的時間里,是不能做其它操作的。同步模式,耗費左右的是。 如果說數組是 PHP 的精髓,數組玩得不6的,根本不能算是會用PHP。那協程對于 Swoole 也是同理,不理解協程去用 Swoole,那就是在瞎用。 首先...
摘要:之后協程化支持已經完善并且支持大量的擴展自動協程化一些基于的框架也蓬勃發展光看著文檔就讓人躍躍欲試但是對于現有舊項目如何引入并啟用協程成了實際場景中的客觀問題由于協程性質及生命周期等原因這并非想象的那么容易本文整理了在現有項目中引入并開啟協 Swoole4之后,協程化支持已經完善,并且支持大量的PHP擴展自動協程化.一些基于Swoole4的框架也蓬勃發展,光看著文檔就讓人躍躍欲試.但是...
摘要:為語言提供了強大的協程編程模式。提供的協程語法借鑒自,在此向開發組致敬協程可以與很好地互補。并發執行使用創建協程,可以讓和兩個函數變成并發執行。協程需要拿到請求的結果。 Swoole4為PHP語言提供了強大的CSP協程編程模式。底層提供了3個關鍵詞,可以方便地實現各類功能。 Swoole4提供的PHP協程語法借鑒自Golang,在此向GO開發組致敬 PHP+Swoole協程可以與...
閱讀 2432·2021-11-22 13:53
閱讀 1126·2021-09-22 16:06
閱讀 1370·2021-09-02 15:21
閱讀 1895·2019-08-30 15:55
閱讀 3116·2019-08-29 11:19
閱讀 1911·2019-08-26 13:23
閱讀 931·2019-08-23 18:23
閱讀 1748·2019-08-23 16:06