Python greenlet實現(xiàn)原理和使用示例
來源:易賢網(wǎng) 閱讀:1251 次 日期:2014-09-25 10:01:11
溫馨提示:易賢網(wǎng)小編為您整理了“Python greenlet實現(xiàn)原理和使用示例”,方便廣大網(wǎng)友查閱!

最近開始研究Python的并行開發(fā)技術(shù),包括多線程,多進(jìn)程,協(xié)程等。逐步整理了網(wǎng)上的一些資料,今天整理了一下greenlet相關(guān)的資料。

并發(fā)處理的技術(shù)背景

并行化處理目前很受重視, 因為在很多時候,并行計算能大大的提高系統(tǒng)吞吐量,尤其在現(xiàn)在多核多處理器的時代, 所以像lisp這種古老的語言又被人們重新拿了起來, 函數(shù)式編程也越來越流行。 介紹一個python的并行處理的一個庫: greenlet。 python 有一個非常有名的庫叫做 stackless ,用來做并發(fā)處理, 主要是弄了個叫做tasklet的微線程的東西, 而greenlet 跟stackless的最大區(qū)別是, 他很輕量級?不夠, 最大的區(qū)別是greenlet需要你自己來處理線程切換, 就是說,你需要自己指定現(xiàn)在執(zhí)行哪個greenlet再執(zhí)行哪個greenlet。

greenlet的實現(xiàn)機制

以前使用python開發(fā)web程序,一直使用的是fastcgi模式.然后每個進(jìn)程中啟動多個線程來進(jìn)行請求處理.這里有一個問題就是需要保證每個請求響應(yīng)時間都要特別短,不然只要多請求幾次慢的就會讓服務(wù)器拒絕服務(wù),因為沒有線程能夠響應(yīng)請求了.平時我們的服務(wù)上線都會進(jìn)行性能測試的,所以正常情況沒有太大問題.但是不可能所有場景都測試到.一旦出現(xiàn)就會讓用戶等好久沒有響應(yīng).部分不可用導(dǎo)致全部不可用.后來轉(zhuǎn)換到了coroutine,python 下的greenlet.所以對它的實現(xiàn)機制做了一個簡單的了解.

每個greenlet都只是heap中的一個python object(PyGreenlet).所以對于一個進(jìn)程你創(chuàng)建百萬甚至千萬個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其實就是一個函數(shù),以及保存這個函數(shù)執(zhí)行時的上下文.對于函數(shù)來說上下文也就是其stack..同一個進(jìn)程的所有的greenlets共用一個共同的操作系統(tǒng)分配的用戶棧.所以同一時刻只能有棧數(shù)據(jù)不沖突的greenlet使用這個全局的棧.greenlet是通過stack_stop,stack_start來保存其stack的棧底和棧頂?shù)?如果出現(xiàn)將要執(zhí)行的greenlet的stack_stop和目前棧中的greenlet重疊的情況,就要把這些重疊的greenlet的棧中數(shù)據(jù)臨時保存到heap中.保存的位置通過stack_copy和stack_saved來記錄,以便恢復(fù)的時候從heap中拷貝回棧中stack_stop和stack_start的位置.不然就會出現(xiàn)其棧數(shù)據(jù)會被破壞的情況.所以應(yīng)用程序創(chuàng)建的這些greenlet就是通過不斷的拷貝數(shù)據(jù)到heap中或者從heap中拷貝到棧中來實現(xiàn)并發(fā)的.對于io型的應(yīng)用程序使用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()

目前所討論的協(xié)程,一般是編程語言提供支持的。目前我所知提供協(xié)程支持的語言包括python,lua,go,erlang, scala和rust。協(xié)程不同于線程的地方在于協(xié)程不是操作系統(tǒng)進(jìn)行切換,而是由程序員編碼進(jìn)行切換的,也就是說切換是由程序員控制的,這樣就沒有了線程所謂的安全問題。

所有的協(xié)程都共享整個進(jìn)程的上下文,這樣協(xié)程間的交換也非常方便。

相對于第二種方案(I/O多路復(fù)用),使得使用協(xié)程寫的程序?qū)⒏拥闹庇^,而不是將一個完整的流程拆分成多個管理的事件處理。協(xié)程的缺點可能是無法利用多核優(yōu)勢,不過,這個可以通過協(xié)程+進(jìn)程的方式來解決。

協(xié)程可以用來處理并發(fā)來提高性能,也可以用來實現(xiàn)狀態(tài)機來簡化編程。我用的更多的是第二個。去年年底接觸python,了解到了python的協(xié)程概念,后來通過pycon china2011接觸到處理yield,greenlet也是一個協(xié)程方案,而且在我看來是更可用的一個方案,特別是用來處理狀態(tài)機。

目前這一塊已經(jīng)基本完成,后面抽時間總結(jié)一下。

總結(jié)一下:

1)多進(jìn)程能夠利用多核優(yōu)勢,但是進(jìn)程間通信比較麻煩,另外,進(jìn)程數(shù)目的增加會使性能下降,進(jìn)程切換的成本較高。程序流程復(fù)雜度相對I/O多路復(fù)用要低。

2)I/O多路復(fù)用是在一個進(jìn)程內(nèi)部處理多個邏輯流程,不用進(jìn)行進(jìn)程切換,性能較高,另外流程間共享信息簡單。但是無法利用多核優(yōu)勢,另外,程序流程被事件處理切割成一個個小塊,程序比較復(fù)雜,難于理解。

3)線程運行在一個進(jìn)程內(nèi)部,由操作系統(tǒng)調(diào)度,切換成本較低,另外,他們共享進(jìn)程的虛擬地址空間,線程間共享信息簡單。但是線程安全問題導(dǎo)致線程學(xué)習(xí)曲線陡峭,而且易出錯。

4)協(xié)程有編程語言提供,由程序員控制進(jìn)行切換,所以沒有線程安全問題,可以用來處理狀態(tài)機,并發(fā)請求等。但是無法利用多核優(yōu)勢。

上面的四種方案可以配合使用,我比較看好的是進(jìn)程+協(xié)程的模式。

更多信息請查看IT技術(shù)專欄

更多信息請查看腳本欄目
易賢網(wǎng)手機網(wǎng)站地址:Python greenlet實現(xiàn)原理和使用示例
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機站點 | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報警專用圖標(biāo)