最近因爲工作需求,需要用下python,作爲項目需求,多線程和多進程首先要考慮進去。在網上trace相關的一些資料,總是發現一些人在說:python下面是假線程。不覺得有點驚奇,據我所知,連java裏面的線程對象(blue thread 虛擬機藍色線程)也是跟系統有很大關係,多半內部包含了一個真實的系統線程對象,而python據官方說,並不是如同go一樣是基於routine的,非真實線程 這種說法估計有誤。。
於是乎,做試驗:
代碼段:
註明:該代碼片斷的外圍還有4個線程執行該部分代碼,故此工作線程遠大於10個
直接spy 進程:
看見了嗎,裏面這麼多工作線程。。。
linux系統,簡單的把手上一個項目在linux上的trace結果發下:
看上圖最上出現4個 worker2,簡單點說就是一個 worker2主進程,並有3個其子進程(線程),上圖最下
顯示4個主進程,所以只有一個worker2。 綜上,python裏面的線程執行體就是真實的系統執行體
今天進一步研究下 python多線程/多進程機制 效率,不再闡述原理,一切‘坑’都產生於GIL機制, 直接上研究代碼了:
import time
from threading import Thread
import multiprocessing
COUNT = 50000000
def countdown(n):
while n>0:
n -= 1
start = time.time()
countdown(COUNT)
end = time.time()
print('Single-trd Time taken in seconds -', end - start)
t1 = Thread(target=countdown, args=(COUNT/2,))
t2 = Thread(target=countdown, args=(COUNT/2,))
start = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
end = time.time()
print('Multi-trd Time taken in seconds -', end - start)
t1 = multiprocessing.Process(target=countdown, args=(COUNT/2,))
t2 = multiprocessing.Process(target=countdown, args=(COUNT/2,))
start = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
end = time.time()
print('Multi-process Time taken in seconds -', end - start)
window平臺執行結果:
('Single-trd Time taken in seconds -', 1.5729999542236328)
('Multi-trd Time taken in seconds -', 4.871000051498413)
('Multi-process Time taken in seconds -', 6.109999895095825)
看到沒有,完全沒救了~~~
linux 平臺執行結果:
(Single-trd Time taken in seconds -', 2.1106820106506348)
('Multi-trd Time taken in seconds -', 2.712383985519409)
('Multi-process Time taken in seconds -', 1.1155731678009033)
linux還好,可以看到 首先,使用多進程(多主進程)是沒毛病,可以大大加快任務完成速度,多線程(子進程),還是慢一些,沒有起到應有的作用。
結論: python下是真線程和真進程,但應用其上愚蠢的GIL機制,僅在linux下使用多進程,纔可能得到 ‘併發’程序的好處。