欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python greenlet實(shí)現(xiàn)原理和使用示例

 更新時(shí)間:2014年09月24日 11:00:11   投稿:junjie  
這篇文章主要介紹了Python greenlet實(shí)現(xiàn)原理和使用示例,greenlet是Python中的一個(gè)并行處理庫(kù),需要的朋友可以參考下

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

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

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

greenlet的實(shí)現(xiàn)機(jī)制

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

每個(gè)greenlet都只是heap中的一個(gè)python object(PyGreenlet).所以對(duì)于一個(gè)進(jìn)程你創(chuàng)建百萬(wàn)甚至千萬(wàn)個(gè)greenlet都沒有問題.

復(fù)制代碼 代碼如下:

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;

每一個(gè)greenlet其實(shí)就是一個(gè)函數(shù),以及保存這個(gè)函數(shù)執(zhí)行時(shí)的上下文.對(duì)于函數(shù)來(lái)說(shuō)上下文也就是其stack..同一個(gè)進(jìn)程的所有的greenlets共用一個(gè)共同的操作系統(tǒng)分配的用戶棧.所以同一時(shí)刻只能有棧數(shù)據(jù)不沖突的greenlet使用這個(gè)全局的棧.greenlet是通過stack_stop,stack_start來(lái)保存其stack的棧底和棧頂?shù)?如果出現(xiàn)將要執(zhí)行的greenlet的stack_stop和目前棧中的greenlet重疊的情況,就要把這些重疊的greenlet的棧中數(shù)據(jù)臨時(shí)保存到heap中.保存的位置通過stack_copy和stack_saved來(lái)記錄,以便恢復(fù)的時(shí)候從heap中拷貝回棧中stack_stop和stack_start的位置.不然就會(huì)出現(xiàn)其棧數(shù)據(jù)會(huì)被破壞的情況.所以應(yīng)用程序創(chuàng)建的這些greenlet就是通過不斷的拷貝數(shù)據(jù)到heap中或者從heap中拷貝到棧中來(lái)實(shí)現(xiàn)并發(fā)的.對(duì)于io型的應(yīng)用程序使用coroutine真的非常舒服.

下面是greenlet的一個(gè)簡(jiǎn)單的??臻g模型(from greenlet.c)

復(fù)制代碼 代碼如下:

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       |

下面是一段簡(jiǎn)單的greenlet代碼.

復(fù)制代碼 代碼如下:

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

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

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

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

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

總結(jié)一下:

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

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

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

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

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

相關(guān)文章

  • pip安裝python庫(kù)的方法總結(jié)

    pip安裝python庫(kù)的方法總結(jié)

    在本篇文章里小編給大家分享了關(guān)于使用pip安裝python庫(kù)的幾種常用方法,有需要的朋友們可以參考下。
    2019-08-08
  • Python中使用socket發(fā)送HTTP請(qǐng)求數(shù)據(jù)接收不完整問題解決方法

    Python中使用socket發(fā)送HTTP請(qǐng)求數(shù)據(jù)接收不完整問題解決方法

    這篇文章主要介紹了Python中使用socket發(fā)送HTTP請(qǐng)求數(shù)據(jù)接收不完整問題解決方法,本文使用一個(gè)循環(huán)解決了數(shù)據(jù)不完整問題,需要的朋友可以參考下
    2015-02-02
  • 淺談pycharm使用及設(shè)置方法

    淺談pycharm使用及設(shè)置方法

    這篇文章主要介紹了淺談pycharm使用及設(shè)置方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 微信跳一跳游戲python腳本

    微信跳一跳游戲python腳本

    這篇文章主要為大家詳細(xì)介紹了微信跳一跳游戲python腳本,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • python采用django框架實(shí)現(xiàn)支付寶即時(shí)到帳接口

    python采用django框架實(shí)現(xiàn)支付寶即時(shí)到帳接口

    這篇文章主要介紹了python采用django框架實(shí)現(xiàn)支付寶即時(shí)到帳接口的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • Pycharm之如何安裝cv2 [python3.6]

    Pycharm之如何安裝cv2 [python3.6]

    這篇文章主要介紹了Pycharm之如何安裝cv2 [python3.6]問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Python實(shí)現(xiàn)的RSS閱讀器實(shí)例

    Python實(shí)現(xiàn)的RSS閱讀器實(shí)例

    這篇文章主要介紹了Python實(shí)現(xiàn)的RSS閱讀器,實(shí)例分析了XML解析實(shí)現(xiàn)RSS閱讀的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 人工智能最火編程語(yǔ)言 Python大戰(zhàn)Java!

    人工智能最火編程語(yǔ)言 Python大戰(zhàn)Java!

    開發(fā)者到底應(yīng)該學(xué)習(xí)哪種編程語(yǔ)言才能獲得機(jī)器學(xué)習(xí)或數(shù)據(jù)科學(xué)這類工作呢?這是一個(gè)非常重要的問題。本文為大家提供作者的答案并解釋原因
    2017-11-11
  • python opencv將表格圖片按照表格框線分割和識(shí)別

    python opencv將表格圖片按照表格框線分割和識(shí)別

    這篇文章主要介紹了python opencv將表格圖片按照表格框線分割和識(shí)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Django model重寫save方法及update踩坑詳解

    Django model重寫save方法及update踩坑詳解

    這篇文章主要介紹了Django model重寫save方法及update踩坑詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-07-07

最新評(píng)論