目錄
並發處理的技術背景
greenlet的實作機制
總結一下:
首頁 後端開發 Python教學 Python greenlet使用介紹及實作原理分析

Python greenlet使用介紹及實作原理分析

Mar 23, 2017 pm 03:55 PM

最近開始研究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)協程有程式語言提供,由程式設計師控制進行切換,所以沒有執行緒安全性問題,可以用來處理狀態機,並發請求等。但是無法利用多核心優勢。

上面的四種方案可以搭配使用,我比較看好的是行程+協程的模式

#

以上是Python greenlet使用介紹及實作原理分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何解決Linux終端中查看Python版本時遇到的權限問題? 如何解決Linux終端中查看Python版本時遇到的權限問題? Apr 01, 2025 pm 05:09 PM

Linux終端中查看Python版本時遇到權限問題的解決方法當你在Linux終端中嘗試查看Python的版本時,輸入python...

在Python中如何高效地將一個DataFrame的整列複製到另一個結構不同的DataFrame中? 在Python中如何高效地將一個DataFrame的整列複製到另一個結構不同的DataFrame中? Apr 01, 2025 pm 11:15 PM

在使用Python的pandas庫時,如何在兩個結構不同的DataFrame之間進行整列複製是一個常見的問題。假設我們有兩個Dat...

如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎? 如何在10小時內通過項目和問題驅動的方式教計算機小白編程基礎? Apr 02, 2025 am 07:18 AM

如何在10小時內教計算機小白編程基礎?如果你只有10個小時來教計算機小白一些編程知識,你會選擇教些什麼�...

Uvicorn是如何在沒有serve_forever()的情況下持續監聽HTTP請求的? Uvicorn是如何在沒有serve_forever()的情況下持續監聽HTTP請求的? Apr 01, 2025 pm 10:51 PM

Uvicorn是如何持續監聽HTTP請求的? Uvicorn是一個基於ASGI的輕量級Web服務器,其核心功能之一便是監聽HTTP請求並進�...

Python中如何通過字符串動態創建對象並調用其方法? Python中如何通過字符串動態創建對象並調用其方法? Apr 01, 2025 pm 11:18 PM

在Python中,如何通過字符串動態創建對象並調用其方法?這是一個常見的編程需求,尤其在需要根據配置或運行...

如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到? 如何在使用 Fiddler Everywhere 進行中間人讀取時避免被瀏覽器檢測到? Apr 02, 2025 am 07:15 AM

使用FiddlerEverywhere進行中間人讀取時如何避免被檢測到當你使用FiddlerEverywhere...

哪些流行的Python庫及其用途? 哪些流行的Python庫及其用途? Mar 21, 2025 pm 06:46 PM

本文討論了諸如Numpy,Pandas,Matplotlib,Scikit-Learn,Tensorflow,Tensorflow,Django,Blask和請求等流行的Python庫,並詳細介紹了它們在科學計算,數據分析,可視化,機器學習,網絡開發和H中的用途

什麼是正則表達式? 什麼是正則表達式? Mar 20, 2025 pm 06:25 PM

正則表達式是在編程中進行模式匹配和文本操作的強大工具,從而提高了各種應用程序的文本處理效率。

See all articles