最近開始研究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真的非常舒服.
|
新聞熱點
疑難解答