協程是一個很早的概念了,早些年的遊戲行業中已經大規模地在使用,像lua、go這些語言中的協程原語已經相對比較完善了,通常來講直接使用就好,可是在系統後臺開發上,出現的時間並不長。
我是作C++方向的後臺開發,目前國內一些公司也開源了一些C++協程庫,但目前來講,仍是在逐步完善的階段。最先接觸的C++協程庫是騰訊微信的 libco,能夠說是至關輕量級的協程,網上關於libco的實現的文章也是相對較多,這裏的話不會去過多地敘述。git
在網上查找關於 libgo 的資料,關於代碼實現的文章並無多少,所以,打算本身看代碼總結,以後的文章中,可能會針libgo和libco的部分功能進行簡單對比,不足之處,但願讀者指出。github
由於工做須要,之前系統的異步框架已經顯得再也不那麼地具備擴展性,異步使得本來很簡單的邏輯(讀->處理->寫),要拆分開來成多個階段,經過回調來響應各個事件,所以有計劃地使用協程來代替。windows
爲何最後選擇了libgo,而沒有選擇更加輕量級的libco ?網上有人給出過二者的性能對比,從自旋鎖、協程的數量以及棧空間、線程支持等各個角度考慮,貌似libgo完勝。
微信
圖片來源於網絡網絡
性能對比數據來源於網絡,並非說libco很差,也許各自應用的場景略有不一樣,libco幾千行的代碼能夠實現一個相對較完備的協程,並且經得住微信後臺龐大的數據流量,自有它的優點。因爲對 libgo 的代碼正在研究當中,所以,暫不對二者評價。框架
不論是什麼樣的協程,最核心的內容,都是在系統發生阻塞的時候上層主動讓出CPU,切換就緒協程的上下文,簡要總結,有以下幾個方面:異步
muhui@ASIAYANG-MB0:~/code/libgo/libgo-master$ ll total 64 -rw-r--r--@ 1 muhui staff 5913 11 7 11:20 CMakeLists.txt -rw-r--r--@ 1 muhui staff 1084 11 7 11:20 LICENSE -rw-r--r--@ 1 muhui staff 8758 11 7 11:20 README.md -rw-r--r--@ 1 muhui staff 4230 11 7 11:20 TODO drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 imgs drwxr-xr-x@ 15 muhui staff 480 11 7 11:20 libgo drwxr-xr-x@ 8 muhui staff 256 11 7 11:20 test drwxr-xr-x@ 6 muhui staff 192 11 7 11:20 third_party drwxr-xr-x@ 20 muhui staff 640 11 7 11:20 tutorial drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 vs_proj muhui@ASIAYANG-MB0:~/code/libgo/libgo-master$ cd libgo/ muhui@ASIAYANG-MB0:~/code/libgo/libgo-master/libgo$ ll total 16 drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 cls drwxr-xr-x@ 19 muhui staff 608 11 7 11:20 common drwxr-xr-x@ 6 muhui staff 192 11 7 11:20 context -rw-r--r--@ 1 muhui staff 1848 11 7 11:20 coroutine.h drwxr-xr-x@ 5 muhui staff 160 11 7 11:20 debug drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 defer -rw-r--r--@ 1 muhui staff 36 11 7 11:20 libgo.h drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 netio drwxr-xr-x@ 5 muhui staff 160 11 7 11:20 pool drwxr-xr-x@ 8 muhui staff 256 11 7 11:20 scheduler drwxr-xr-x@ 7 muhui staff 224 11 7 11:20 sync drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 task drwxr-xr-x@ 4 muhui staff 128 11 7 11:20 timer
libgo 作的較好的一點是增長了對windows 環境的支持等,咱們只針對 Linux 環境作研究。函數
vs_proj:VS 環境下如何使用libgo。性能
在libgo目錄下
咱們知道,協程是用戶態線程,所以libco的話是不支持線程的。但在libgo中,線程一樣是支持的,這於它的調度方式有關。
首先咱們要說的一點是,在libgo中,每一個協程是一個task,libgo 的調度並非直接做用於協程,是經過間接調度實現的。
libgo中有調度器(scheduler)和執行器(processer)的概念:
直接負責協程調度的是執行器,它會在協程阻塞的時候切出上下文,並切入一個就緒協程的上下文去繼續處理,當沒有可執行的協程時,執行器就會阻塞等待,當有新到來的任務時,會繼續處理;
負責管理執行器的是調度器,對調度器而言,每一個執行器是一個單獨的線程,調度器作的最主要的工做,就是平衡各個執行器中的協程數量,防止飢餓效應,部分執行器過忙,部分執行器卻沒有task可執行,另外,若是某個執行器卡住,調度器也會將執行器中的可運行協程取出,放到負載最低的執行器上。
以下圖:
關於代碼實現會在下一篇中敘述。