日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python异步io多文件_Python 异步 IO 性能又上一层楼

發布時間:2025/3/20 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python异步io多文件_Python 异步 IO 性能又上一层楼 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近看源碼的過程中,發現了一個比較有意思的庫,aiomultiprocess,我認為他確實是 Python 升級到 3.8 之后一個特性的總結庫,包括靜態檢查和性能提升。

這個是作者提供的一個 IO 性能對比圖:

因為其場景主要是圖片上傳,所以性能對比僅供參考,從邏輯上面推理,按照作者的思路確實可以提升不少 IO 性能。

作者實際上結合了 Python 的三個特性:

multiprocess

asyncio

map/reduce

這三個庫其實都是很普通的庫,使用過 Python3 之后的版本,基本上都會接觸到,那為什么作者可以從這三個庫上面獲取到比較好的性能?主要是因為他在這三個庫的基礎上優化了協程的調度方式。

優化后的協程調度方式更加類似于 Golang 的調度方式,唯一的差異是少了搶占式調度的思路,僅僅使用了 RoundRobin 的方式,所以 IO 性能跟 Go 還有差距,但是肯定比 Nodejs 的性能要好一些。

協程、線程、進程之間的區別

這個問題對于剛接觸的人來說很復雜。先說進程和線程,進程和線程都是操作系統的概念,線程必須要在進程里面運行,另外進程是獨立的存儲空間,而線程的存儲空間是他所在進程的一部分,所以線程的開銷比進程小,線程的切換是邏輯上面的切換,但是進程的切換實際發生在物理 CPU 上面的;協程可以認為是比線程更加輕量的執行單元,他使用了線程的存儲空間,協程之間通過 function 級別的 namespace 區分存儲單元。綜合來看他們三者最大的差異是在所在的運行時以及切換的開銷。

CPU 上面的 4 核 8 線程和我們說的線程是什么關系?4 核 8 線程的意思是每個 CPU 核上面有兩個獨立的線程工作單元,所以 4 個核心一共有 8 個線程,這 8 個線程可以看做是 8 條流水線,我們上文討論的線程、進程、協程全部都是操作系統邏輯上面的概念,與這個關系不大。

在一個 4 核 8 線程的機器上面,理論上可以同時運行 8 個進程。

如果進程數量大于 CPU 實際的線程數怎么辦?操作系統進程有很多,開機就有 100+,那么實際上我們的 CPU 線程數是有限的,這 100+ 的系統進程需要按照不同的優先級由操作系統分時調度在不同的 CPU 線程上面工作。

如何理解并行和并發?并行和并發都是指事情同時發生,區別是...? emm 好像不是很好回答,唯一能夠準確描述的是并行是獨立事件,并發是關聯事件。舉個例子:一條四車道的路可以并排行駛 4 個車輛,但是如果這條路只有一車道的話,那么也可以行駛著四個車輛,區別是有的車輛需要排隊了,同時行駛的我們認為是并行,排隊走同一個車道的我們認為是并發。

當系統的進程數量 100 大于 CPU 的實際線程數量 8 時,那么系統并行數是 8,并發數量是 100。這種方法同樣適用于描述線程和協程。

Python 為什么慢?

Python 解釋器是單進程的。一個 Python 解釋器是一個單進程的應用,再加上 GIL 鎖,導致在進程里面不能并行執行線程,不同的線程是分時使用進程所在的 CPU 執行時間的。

因為 GIL 所以即使現在有充足的系統資源,那么 Request 1,Request 2,Request 3 也沒有辦法同時發生。

動態類型。動態類型讓 Python 寫起來非常的簡單,所有的類型默認都是對象,所以編寫代碼非常的簡單直接,但是執行的時候,解釋器需要去推導類型,并動態檢查類型有沒有問題,所以導致運行時的任務比較重,相對于靜態編譯語言,速度跟不上。

協程的基本模型

協程實際上就是一個 function 級別的任務,分成兩類,一類跟 IO 有關系,一類跟 IO 沒有關系。Golang 的優勢是能很好的處理計算和 IO 相關的協程,目前在 Python 里面勉強可以解決跟 IO 相關的協程。

IO 實際上是沒法避免的,比如磁盤訪問,網絡 IO 等,他一定會有一定的等待時間,所以無論怎么調度,都會有 IO 等待,為了解決這個問題,操作系統引入了不少的模型:select、poll、epoll 等。

那么基本上所有的編程語言都是利用了系統調用,也就是使用這些模型來解決問題,但是他們只可能比操作系統差,不能更好,因為有些編程語言誕生的比較早,大規模 IO 問題當時還沒遇到,說白了也就是那個時候沒有那么多用戶。

我使用 Python 語言大致經歷了:進程 IO,線程 IO,協程 IO,協程池等,目前看到最優的就是 facebook 的這個 aiomultiprocess。

IO 協程也就是把 IO 封裝成 function 級別的單元來調度,然后利用操作系統的 IO 調度模型,提升應用程序的性能,相對于進程和線程來說對于系統資源的利用更加合理,而且存儲開銷更加小,調度開銷也小很多。

epoll 基本模型

epoll 是目前主流的 IO 調度模型,調度性能最優秀的其實是微軟的 IOCP,但是因為閉源,而且系統應用開發一般集中在 linux 所以對他也了解的不多。

epoll 實際上把 IO 等待問題集中交給操作系統處理,并要求操作系統出現我關心的事件的時候提醒我(比如某個文件描述符可以讀取,可以寫入,出現了錯誤等),把 IO 問題交給操作系統之后,應用程序就可以更加集中的去處理業務問題,而操作系統有更好的方式處理 IO,這就是站在了巨人的肩膀上。

Python 中的線程,進程,協程處理 IO 問題

Python 中使用進程處理問題相當于利用多核去等待 IO,相對于線程來說,使用了多核等待,線程是單核輪訓等待,使用多線程和多進程處理 IO 問題性能上面差異并不是很大,但是系統開銷很大,特別的進程的開銷還要大于線程,很容易導致操作系統卡頓。

協程因為開銷小,所以可以同時創建上萬的協程,所以其并發能力遠大于進程和線程,因為總需要等待 IO 時間,所以單進程內部不同的協程之間通過共享時間片的方式也是合理的。

AsyncIO 和協程之間的關系

AsyncIO 和協程之間并沒有什么關系,但是他們通常同時出現,主要是 AsyncIO 需要依附于協程作為容器,普通的協程只是在發生 IO 等待的時候交出了執行權限給其他協程,告訴其他人:我現在需要等待 IO 了,你先使用 CPU。但是在 AsyncIO 中,我們使用 epoll 配合 IO api,實際的調度是 epoll 來管理 IO,普通的協程還是利用 Python 應用程序管理 IO,所以本質上還是有很大差別的。

aiomultiprocess 為什么更快?

aiomultiprocess 將異步 IO 和多進程結合起來了,很好的利用了多核和異步 IO 的優勢,前面說到 Python 是單進程的,所以即使有 AsyncIO 那么也并沒有充分利用操作系統的資源,相對來說還不是很快,但是結合了多進程之后,性能就可以線性增長了。

Golang 為什么更快?

既然充分了利用了多核,那么為什么還是比 Golang 慢?主要還是調度器的原因,Golang 是搶占式調度,目前 facebook 的這個版本主要是通過 RoundRobin 調度的,默認認為每一個任務和每一個 worker 的執行時間是固定的,但是如果出現比較意外的情況,比如系統資源占用,就會導致進程出現假死,那么依附在進程隊列上面的任務也不能得到調度,為此作者增加了進程的生命之周期管理 TTL,執行一定的任務之后,自毀并重新創建進程,這種方式可以緩解調度問題,但是粒度還是比較粗。

總結

aiomultiprocess 這個庫可以說是很棒的一個 IO 模型庫了,合理的利用多核來完成 IO 任務,相對于單獨使用線程,進程,異步 IO 來說,會有一個不錯的提升,可廣泛用于大規模的異步 IO 處理,比如發送郵件,上傳數據等。

總結

以上是生活随笔為你收集整理的python异步io多文件_Python 异步 IO 性能又上一层楼的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。