【多進程爹耗、多線程鲸沮、協(xié)程+異步】對比測試

目錄

概念介紹

測試環(huán)境

開始測試

測試【單進程單線程】

測試【多進程 并行】

測試【多線程 并發(fā)】

測試【協(xié)程 + 異步】

結(jié)果對比

繪圖展示

概念介紹

首先簡單介紹幾個概念:

進程和線程

進程就是一個程序在一個數(shù)據(jù)集上的一次動態(tài)執(zhí)行過程(數(shù)據(jù)集是程序在執(zhí)行過程中所需要使用的資源)讼溺。

線程也叫輕量級進程怒坯,它是一個基本的 CPU 執(zhí)行單元剔猿,是比進程更小的能獨立運行的基本單位嬉荆。

進程和線程的關(guān)系:

一個線程只能屬于一個進程,而一個進程可以有多個線程汪茧,但至少有一個線程舱污。

資源分配給進程扩灯,同一進程的所有線程共享該進程的所有資源。

CPU 分給線程珠插,即真正在 CPU 上運行的是線程丧失。

并行和并發(fā)

并行處理是計算機系統(tǒng)中能同時執(zhí)行兩個或更多個處理的一種計算方法。并行處理可同時工作于同一程序的不同方面琳拭,其主要目的是節(jié)省大型和復雜問題的解決時間白嘁。

并發(fā)處理指一個時間段中有幾個程序都處于已啟動運行到運行完畢之間絮缅,且這幾個程序都是在同一個 CPU 上運行呼股,但任一個時刻點上只有一個程序在 CPU 上運行。

并發(fā)的關(guān)鍵是你有處理多個任務的能力吸奴,不一定要同時则奥。并行的關(guān)鍵是你有同時處理多個任務的能力读处。所以說唱矛,并行是并發(fā)的子集。多進程是并行的管闷,多線程是并發(fā)的渐北。

同步和異步

同步就是指一個進程在執(zhí)行某個請求的時候阿逃,若該請求需要一段時間才能返回信息,那么這個進程將會一直等待下去搀菩,直到收到返回信息才繼續(xù)執(zhí)行下去肪跋。

異步是指進程不需要一直等下去,而是繼續(xù)執(zhí)行下面的操作州既,不管其他進程的狀態(tài)吴叶。當有消息返回時系統(tǒng)會通知進程進行處理,這樣可以提高執(zhí)行的效率实束。

舉個例子逊彭,打電話時就是同步通信侮叮,發(fā)短息時就是異步通信。

測試環(huán)境

進行對比測試之前谷异,我們先來創(chuàng)建一個合適的實驗環(huán)境:

???????模擬一個需要等待一定時間才可以獲取返回結(jié)果的網(wǎng)頁锦聊。

如果直接用百度孔庭、CSDN 等站點的話,一方面響應太快怎抛、難以看出各種方法的差距芽淡,另一方面響應速度會受網(wǎng)速影響挣菲、每次發(fā)送請求獲取響應所需的時間不完全一致導致重復實驗結(jié)果差距較大掷邦,所以在此用 Flask 模擬一個本地慢速服務器抚岗。

flask_server.py 代碼如下:

from flask import Flask? ? # pip install flask

import time

app = Flask(__name__)

@app.route('/')

def index():

? ? time.sleep(3)? ? # 休眠 3 秒再返回結(jié)果

? ? return 'Hello!'

if __name__ == '__main__':

? ? app.run(threaded=True)? # 以多線程模式啟動服務


啟動之后宣蔚,F(xiàn)lask 服務默認在 127.0.0.1:5000 上運行认境,控制臺輸出結(jié)果如下:

* Serving Flask app "flask_server" (lazy loading)

* Environment: production

? WARNING: Do not use the development server in a production environment.

? Use a production WSGI server instead.

* Debug mode: off

* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)


在瀏覽器中訪問 http://127.0.0.1:5000/ 等待 3 秒即會出現(xiàn) Hello! 頁面叉信,表明簡單的慢速服務器搭建完成!

開始測試

首先導入需要的模塊鉴未,以請求 10 次為例準備 urls铜秆,再定義一個 get_html_text() 函數(shù):

import requests

import time

# 用于多進程

from multiprocessing import Process

# 用于多線程

from threading import Thread

# 用于協(xié)程+異步

import asyncio

import aiohttp? ? ? # pip install aiohttp

urls = ['http://127.0.0.1:5000' for _ in range(10)]

def get_html_text(url):

? ? response = requests.get(url)

? ? return response.text


測試【單進程單線程】

start = time.time()

for url in urls:

? ? result = get_html_text(url)

? ? print(result)

end = time.time()

print('【單進程單線程】耗時:%s 秒' %(end - start))


結(jié)果如下:

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

【單進程單線程】耗時:30.15605854988098 秒


測試【多進程 并行】

start = time.time()

processes = []

for url in urls:

? ? p = Process(target=get_html_text, args=(url,))

? ? processes.append(p)

? ? p.start()

for p in processes:

? ? p.join()

? ? print('Hello!')

end = time.time()

print('【多進程? 并行】耗時:%s 秒' %(end - start))


結(jié)果如下(測試電腦為 4 核 CPU连茧,核心數(shù)越大加速越明顯):

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

【多進程? 并行】耗時:5.511234283447266 秒


測試【多線程 并發(fā)】

start = time.time()

threads = []

for url in urls:

? ? t = Thread(target=get_html_text, args=(url,))

? ? threads.append(t)

? ? t.start()

for t in threads:

? ? t.join()

? ? print('Hello!')

end = time.time()

print('【多線程? 并發(fā)】耗時:%s 秒' %(end - start))


結(jié)果如下:

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

【多線程? 并發(fā)】耗時:3.030653953552246 秒


測試【協(xié)程 + 異步】

# 因為 requests 模塊不支持異步操作啸驯,需要借助 aiohttp 模塊

async def get_html_text_async(url):

? ? async with aiohttp.ClientSession() as session:

? ? ? ? async with session.get(url) as response:

? ? ? ? ? ? text = await response.text()

? ? ? ? ? ? return text

start = time.time()

tasks = [asyncio.ensure_future(get_html_text_async(url)) for url in urls]

loop = asyncio.get_event_loop()

loop.run_until_complete(asyncio.wait(tasks))

for task in tasks:

? ? print(task.result())

end = time.time()

print('【協(xié)程 ++ 異步】耗時:%s 秒' %(end - start))


結(jié)果如下:

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

Hello!

【協(xié)程 ++ 異步】耗時:3.046288251876831 秒


結(jié)果對比

len(urls)==1:

len(urls)==4:

len(urls)==10:

len(urls)==100:

單進程單線程是將 n 次請求順次執(zhí)行,每次要等待 3 秒才能返回結(jié)果宅楞,故耗時 3n+ 秒;

多進程-并行處理則利用 CPU 的多核優(yōu)勢距淫,在同一時間并行地執(zhí)行多個任務榕暇,可以大大提高執(zhí)行效率,但系統(tǒng)實現(xiàn)多進程前需要一些準備工作彤枢、將耗費大量時間。

多線程-并發(fā)處理和協(xié)程+異步的耗時由單進程單線程的 3n+ 秒變成了 3+ 秒!

前者是 n 個請求幾乎同時進行盟猖、幾乎同時得到響應返回結(jié)果换棚。

后者是每當請求任務遇到阻塞(time.sleep(3))時被掛起,n 個任務都處于掛起狀態(tài)后等待 3 秒娘汞,n 個請求幾乎同時都有了響應你弦,然后掛起的任務被喚醒接著執(zhí)行燎孟,輸出請求結(jié)果,最后耗時:3 秒?醭ァ(多出來的時間是 IO 時延)

注意:

搭建的實驗環(huán)境是慢速服務器萍程,若不進行 time.sleep(3) 休眠 3 秒再返回 而是立即響應的話兔仰,單進程單線程的實際耗時則會大大縮短乎赴,請求次數(shù)少的話甚至會超過多進程。

而且筆者在 Windows 4 核 CPU 環(huán)境下測試缔赠,最多開啟 4 個進程嗤堰,未能發(fā)揮多進程的真實實力。

另外告匠,多進程后专、多線程還可以通過進程池戚哎、線程池來實現(xiàn)嫂用,與文中方法耗時基本一致嘱函,故未做展示;多進程或多線程與協(xié)程異步IO結(jié)合的效率尚待測試疏唾。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荸实,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子准给,更是在濱河造成了極大的恐慌露氮,老刑警劉巖畔规,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叁扫,死亡現(xiàn)場離奇詭異,居然都是意外死亡畜埋,警方通過查閱死者的電腦和手機莫绣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悠鞍,“玉大人对室,你說我怎么就攤上這事。” “怎么了掩宜?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵蔫骂,是天一觀的道長。 經(jīng)常有香客問我牺汤,道長辽旋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任檐迟,我火速辦了婚禮,結(jié)果婚禮上怔匣,老公的妹妹穿的比我還像新娘。我一直安慰自己剿骨,他們只是感情好,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般牙甫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脏答,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天羡洁,我揣著相機與錄音筑煮,去河邊找鬼。 笑死,一個胖子當著我的面吹牛软啼,可吹牛的內(nèi)容都是我干的贞间。 我是一名探鬼主播闪唆,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼帆调,長吁一口氣:“原來是場噩夢啊……” “哼番刊!你這毒婦竟也來了蝉绷?” 一聲冷哼從身側(cè)響起佳晶,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤菇篡,失蹤者是張志新(化名)和其女友劉穎嗜暴,沒想到半個月后触徐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡孝鹊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年柳骄,在試婚紗的時候發(fā)現(xiàn)自己被綠了丝里。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布榕栏,位于F島的核電站妨托,受9級特大地震影響医清,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一躯枢、第九天 我趴在偏房一處隱蔽的房頂上張望得糜。 院中可真熱鬧治宣,春花似錦布持、人聲如沸捉超。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓絮爷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容