Python greenlet使用介紹及實現原理
最近開始研究Python的並行開發技術,包括多執行緒,多程式,協程等。逐步整理了網上的一些資料,今天整理了一下greenlet相關的資料。
併發處理的技術背景
並行化處理目前很受重視, 因為在很多時候,平行計算能大大的提高系統吞吐量,尤其在現在多核多處理器的時代, 所以像lisp這種古老的語言又被人們重新拿了起來, 函數語言程式設計也越來越流行。 介紹一個python的並行處理的一個庫: greenlet。 python 有一個非常有名的庫叫做 stackless ,用來做併發處理, 主要是弄了個叫做tasklet的微執行緒的東西, 而greenlet 跟stackless的最大區別是, 他很輕量級?不夠, 最大的區別是greenlet需要你自己來處理執行緒切換, 就是說,你需要自己指定現在執行哪個greenlet再執行哪個greenlet。
greenlet的實現機制
以前使用python開發web程式,一直使用的是fastcgi模式.然後每個程式中啟動多個執行緒來進行請求處理.這裡有一個問題就是需要保證每個請求響應時間都要特別短,不然只要多請求幾次慢的就會讓伺服器拒絕服務,因為沒有執行緒能夠響應請求了.平時我們的服務上線都會進行效能測試的,所以正常情況沒有太大問題.但是不可能所有場景都測試到.一旦出現就會讓使用者等好久沒有響應.部分不可用導致全部不可用.後來轉換到了coroutine,python 下的greenlet.所以對它的實現機制做了一個簡單的瞭解.
每個greenlet都只是heap中的一個python object(PyGreenlet).所以對於一個程式你建立百萬甚至千萬個greenlet都沒有問題.
typedef struct _greenlet { PyObject_HEAD char* stack_start; char* stack_stop; char* stack_copy; intptr_t stack_saved; struct _greenlet* stack_prev; struct _greenlet* parent; PyObject* run_info; struct _frame* top_frame; int recursion_depth; PyObject* weakreflist; PyObject* exc_type; PyObject* exc_value; PyObject* exc_traceback; PyObject* dict; } PyGreenlet;
每一個greenlet其實就是一個函式,以及儲存這個函式執行時的上下文.對於函式來說上下文也就是其stack..同一個程式的所有的greenlets共用一個共同的作業系統分配的使用者棧.所以同一時刻只能有棧資料不衝突的greenlet使用這個全域性的棧.greenlet是通過stack_stop,stack_start來儲存其stack的棧底和棧頂的,如果出現將要執行的greenlet的stack_stop和目前棧中的greenlet重疊的情況,就要把這些重疊的greenlet的棧中資料臨時儲存到heap中.儲存的位置通過stack_copy和stack_saved來記錄,以便恢復的時候從heap中拷貝回棧中stack_stop和stack_start的位置.不然就會出現其棧資料會被破壞的情況.所以應用程式建立的這些greenlet就是通過不斷的拷貝資料到heap中或者從heap中拷貝到棧中來實現併發的.對於io型的應用程式使用coroutine真的非常舒服.
下面是greenlet的一個簡單的棧空間模型(from greenlet.c)
A PyGreenlet is a range of C stack addresses that must be saved and restored in such a way that the full range of the stack contains valid data when we switch to it. Stack layout for a greenlet: | ^^^ | | older data | | | stack_stop . |_______________| . | | . | greenlet data | . | in stack | . * |_______________| . . _____________ stack_copy + stack_saved . | | | | . | data | |greenlet data| . | unrelated | | saved | . | to | | in heap | stack_start . | this | . . |_____________| stack_copy | greenlet | | | | newer data | | vvv |
下面是一段簡單的greenlet程式碼.
from greenlet import greenlet def test1(): print 12 gr2.switch() print 34 def test2(): print 56 gr1.switch() print 78 gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
目前所討論的協程,一般是程式語言提供支援的。目前我所知提供協程支援的語言包括python,lua,go,erlang, scala和rust。協程不同於執行緒的地方在於協程不是作業系統進行切換,而是由程式設計師編碼進行切換的,也就是說切換是由程式設計師控制的,這樣就沒有了執行緒所謂的安全問題。
所有的協程都共享整個程式的上下文,這樣協程間的交換也非常方便。
相對於第二種方案(I/O多路複用),使得使用協程寫的程式將更加的直觀,而不是將一個完整的流程拆分成多個管理的事件處理。協程的缺點可能是無法利用多核優勢,不過,這個可以通過協程+程式的方式來解決。
協程可以用來處理併發來提高效能,也可以用來實現狀態機來簡化程式設計。我用的更多的是第二個。去年年底接觸python,瞭解到了python的協程概念,後來通過pycon china2011接觸到處理yield,greenlet也是一個協程方案,而且在我看來是更可用的一個方案,特別是用來處理狀態機。
目前這一塊已經基本完成,後面抽時間總結一下。
總結一下:
1)多程式能夠利用多核優勢,但是程式間通訊比較麻煩,另外,程式數目的增加會使效能下降,程式切換的成本較高。程式流程複雜度相對I/O多路複用要低。
2)I/O多路複用是在一個程式內部處理多個邏輯流程,不用進行程式切換,效能較高,另外流程間共享資訊簡單。但是無法利用多核優勢,另外,程式流程被事件處理切割成一個個小塊,程式比較複雜,難於理解。
3)執行緒執行在一個程式內部,由作業系統排程,切換成本較低,另外,他們共享程式的虛擬地址空間,執行緒間共享資訊簡單。但是執行緒安全問題導致執行緒學習曲線陡峭,而且易出錯。
4)協程有程式語言提供,由程式設計師控制進行切換,所以沒有執行緒安全問題,可以用來處理狀態機,併發請求等。但是無法利用多核優勢。
上面的四種方案可以配合使用,我比較看好的是程式+協程的模式。
相關文章
- Flink sql實現原理及Apache Calcite介紹SQLApache
- Python APScheduler介紹及使用Python
- python中greenlet基本使用Python
- tornado原理介紹及非同步非阻塞實現方式非同步
- Kafka的原理介紹及實踐Kafka
- golang實現常用集合原理介紹Golang
- 簡單介紹numpy實現RNN原理實現RNN
- Docker容器實現原理及容器隔離性踩坑介紹Docker
- BiLSTM介紹及程式碼實現
- CNN介紹及程式碼實現CNN
- 基於FPGA的乘法器原理介紹及設計實現FPGA
- 簡單易懂的 Go 泛型使用和實現原理介紹Go泛型
- KVO使用及實現原理
- Docker的原理及特性介紹Docker
- rxjs Observable filter Operator 的實現原理介紹JSFilter
- sku演算法介紹及實現演算法
- 快速傅立葉變換原理介紹及遞迴程式碼實現遞迴
- 中文分詞原理及常用Python中文分詞庫介紹中文分詞Python
- Swagger介紹及使用Swagger
- vagrant介紹及使用
- Canal 介紹及使用
- 條形碼生成原理介紹及簡介
- 常見排序原理及 python 實現排序Python
- 《機器學習Python實現_10_10_整合學習_xgboost_原理介紹及迴歸樹的簡單實現》機器學習Python
- Gin框架介紹及使用框架
- Tomcat 介紹及使用教程Tomcat
- Docker基本介紹及使用Docker
- mybatis原理,配置介紹及原始碼分析MyBatis原始碼
- Spring Cloud Stream 體系及原理介紹SpringCloud
- 單目測距的基本介紹和實現原理
- Python JWT 介紹和使用PythonJWT
- 掃碼登入認證技術原理介紹及實踐
- Lombok介紹及使用方法Lombok
- netcat 命令介紹及使用示例
- Nacos 配置中心介紹及使用
- JEB工具的介紹及使用
- OutputStreamWriter介紹&程式碼實現和InputStreamReader介紹&程式碼實現
- 《AOP挖掘記》概念介紹及原理初探(一)
- Angular 依賴注入機制實現原理的深入介紹Angular依賴注入