Python執行緒和協程CPU資源利用率測試

  前言介紹

  協程 ,又稱為微執行緒,它是實現多任務的另一種方式,只不過是比執行緒更小的執行單元。因為它自帶CPU的上下文,這樣只要在合適的時機,我們可以把一個協程切換到另一個協程。通俗的理解: 在一個執行緒中的某個函數中,我們可以在任何地方保存當前函數的一些臨時變數等資訊,然後切換到另外一個函數中執行,注意不是通過調用函數的方式做到的 ,並且切換的次數以及什麼時候再切換到原來的函數都由開發者自己確定。

  協程與執行緒的差異:
  在實現多任務時, 執行緒切換從系統層面遠不止保存和恢復CPU上下文這麼簡單。作業系統為了程式運行的高效性,每個執行緒都有自己快取Cache等等數據,作業系統還會幫你做這些數據的恢復操作,所以執行緒的切換非常耗性能。但是協程的切換隻是單純地操作CPU的上下文,所以一秒鐘切換個上百萬次系統都抗的住。

  下面舉例說明協程和執行緒使用過程中CPU消耗情況

  1、創建執行緒測試文件 threads.py,程式碼內容如下:

import time
from threading import Thread


def hello(x):
    """測試任務"""
    for i in range(50):
        print(f'測試執行緒{x}')
        time.sleep(1)  # 模擬


def thread_test():
    """創建1000個執行緒並進行任務"""
    for i in range(1000):
        Thread(target=hello, args=(i,)).start()


if __name__ == '__main__':
    thread_test()

  2、創建協程測試文件 gevents.py,程式碼內容如下:

import gevent

from gevent import monkey

monkey.patch_all()
import time


def hello(x):
    """測試任務"""
    for i in range(50):
        print(f'測試協程{x}')
        time.sleep(1)


def gevent_test():
    """創建1000個協程任務"""
    gevent.joinall([gevent.spawn(hello, i) for i in range(1000)])


if __name__ == '__main__':
    gevent_test()

 

運行結果:

 

結論:開啟1000個執行緒任務所消耗的CPU是13.5%,開啟1000個協程任務消耗的CPU是 1.1%,協程遠優於執行緒

 

眾所周知 ,多執行緒除了會給cpu帶來切換上下文的開銷,還會產生資源競爭,想要用多執行緒,免不了加鎖操作,協程完美的避免了這個問題。

所以在多執行緒和協程都能適用的場景下,協程是一個更好的選擇。