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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python异步和多线程_Python 异步 IO(asyncio)、多进程、多线程性能对比

發(fā)布時間:2023/12/19 python 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python异步和多线程_Python 异步 IO(asyncio)、多进程、多线程性能对比 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

IO 密集型應(yīng)用

IO 密集型應(yīng)用CPU等待IO時間遠(yuǎn)大于CPU 自身運(yùn)行時間,太浪費(fèi);常見的 IO 密集型業(yè)務(wù)包括:瀏覽器交互、磁盤請求、網(wǎng)絡(luò)爬蟲、數(shù)據(jù)庫請求等

image.png

Python 世界對于 IO 密集型場景的并發(fā)提升有 3 種方法:多進(jìn)程、多線程、異步 IO(asyncio);理論上講asyncio是性能最高的,原因如下:

1.進(jìn)程、線程會有CPU上下文切換

2.進(jìn)程、線程需要內(nèi)核態(tài)和用戶態(tài)的交互,性能開銷大;而協(xié)程對內(nèi)核透明的,只在用戶態(tài)運(yùn)行

3.進(jìn)程、線程并不可以無限創(chuàng)建,最佳實踐一般是 CPU*2;而協(xié)程并發(fā)能力強(qiáng),并發(fā)上限理論上取決于操作系統(tǒng)IO多路復(fù)用(Linux下是 epoll)可注冊的文件描述符的極限

那asyncio的實際表現(xiàn)是否如理論上那么強(qiáng),到底強(qiáng)多少呢?我構(gòu)建了如下測試場景:

訪問500臺 DB,并sleep 100ms模擬業(yè)務(wù)查詢

方法 1;順序串行一臺臺執(zhí)行

方法 2:多進(jìn)程

方法 3:多線程

方法 4:asyncio

方法 5:asyncio+uvloop

最后的asyncio+uvloop和官方asyncio 最大不同是用 Cython+libuv 重新實現(xiàn)了asyncio 的事件循環(huán)(event loop)部分,官方測試性能是 node.js的 2 倍,持平 golang。

以下測試代碼需要 Pyhton3.7+:

順序串行一臺臺執(zhí)行

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import records

user=xx

pass=xx

port=xx

hosts= [....] # 500臺 db列表

def query(host):

conn = records.Database(

f'mysql+pymysql://{user}:{pass}@{host}:{port}/mysql?charset=utf8mb4')

rows = conn.query('select sleep(0.1);')

print(rows[0])

def main():

for h in hosts:

query(h)

# main entrance

if __name__ == '__main__':

main()

多進(jìn)程

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

from concurrent import futures

import records

user=xx

pass=xx

port=xx

hosts= [....] # 500臺 db列表

def query(host):

conn = records.Database(

f'mysql+pymysql://{user}:{pass}@{host}:{port}/mysql?charset=utf8mb4')

rows = conn.query('select sleep(0.1);')

print(rows[0])

def main():

with futures.ProcessPoolExecutor() as executor:

for future in executor.map(query,hosts):

pass

# main entrance

if __name__ == '__main__':

main()

多線程

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

from concurrent import futures

import records

user=xx

pass=xx

port=xx

hosts= [....] # 500臺 db列表

def query(host):

conn = records.Database(

f'mysql+pymysql://{user}:{pass}@{host}:{port}/mysql?charset=utf8mb4')

rows = conn.query('select sleep(0.1);')

print(rows[0])

def main():

with futures.ThreadPoolExecutor() as executor:

for future in executor.map(query,hosts):

pass

# main entrance

if __name__ == '__main__':

main()

asyncio

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import asyncio

from databases import Database

user=xx

pass=xx

port=xx

hosts= [....] # 500臺 db列表

async def query(host):

DATABASE_URL = f'mysql+pymysql://{user}:{pass}@{host}:{port}/mysql?charset=utf8mb4'

async with Database(DATABASE_URL) as database:

query = 'select sleep(0.1);'

rows = await database.fetch_all(query=query)

print(rows[0])

async def main():

tasks = [asyncio.create_task(query(host)) for host in hosts]

await asyncio.gather(*tasks)

# main entrance

if __name__ == '__main__':

asyncio.run(main())

asyncio+uvloop

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import asyncio

import uvloop

from databases import Database

user=xx

pass=xx

port=xx

hosts= [....] # 500臺 db列表

async def query(host):

DATABASE_URL = f'mysql+pymysql://{user}:{pass}@{host}:{port}/mysql?charset=utf8mb4'

async with Database(DATABASE_URL) as database:

query = 'select sleep(0.1);'

rows = await database.fetch_all(query=query)

print(rows[0])

async def main():

tasks = [asyncio.create_task(query(host)) for host in hosts]

await asyncio.gather(*tasks)

# main entrance

if __name__ == '__main__':

uvloop.install()

asyncio.run(main())

運(yùn)行時間對比

方式

運(yùn)行時間

串行

1m7.745s

多進(jìn)程

2.932s

多線程

4.813s

asyncio

1.068s

asyncio+uvloop

0.750s

可以看出: 無論多進(jìn)程、多進(jìn)程還是asyncio都能大幅提升IO 密集型場景下的并發(fā),但asyncio+uvloop性能最高,運(yùn)行時間只有原始串行運(yùn)行時間的 1/90,相差快 2 個數(shù)量級了!

內(nèi)存占用對比

串行

image.png

多進(jìn)程

image.png

多線程

image.png

asyncio

image.png

asyncio+uvloop

image.png

可以看出asyncio+uvloop內(nèi)存占用表現(xiàn)仍然最優(yōu),只有 60M;而多進(jìn)程占用多達(dá) 1.4G,果然創(chuàng)建進(jìn)程是個十分重的操作~

總結(jié)

asyncio 無論運(yùn)行時間還是內(nèi)存占用都遠(yuǎn)優(yōu)于多進(jìn)程、多線程,配合 uvloop 性能還能進(jìn)一步提升,在 IO 密集型業(yè)務(wù)中可以優(yōu)先使用 asyncio。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的python异步和多线程_Python 异步 IO(asyncio)、多进程、多线程性能对比的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。