同時実行および戻り結果の比較について(py版)

3726 ワード

前言

py GIL, , .
 

threading multiprocessing, concurrent.futures asyncio(3.5以降のコモンシップ)gevent(monkey_patchと呼ばれることが多い)
ソースコードについては、興味があり、研究して、やはり収穫があります.日を改めて開編する.asyncioはyield魔改に基づいており、全体の生態はまだ成熟しておらず、ツッコミを入れられることが多いが、私が現在使っている限りでは、悪くない.
monkey_patchは長時間のオンライン検証やコードの侵入性がなく、性能は信頼できる.
同時的な考慮に基づいて、これらはすべて良い考え方です.

义齿


この2つのapiの差は多くなく、異なるといえばmultiprocessingは結果を返すことができ、threadingは結果を返すことができ、一般的に2つの考え方はキューやクラスで1層をカプセル化することである.

Multiprocessingは結果を返します

def req_multi(url:str, result: dict):
    r = requests.get(url)
    result[url] = r

def main_multi():
    process_manager = multiprocessing.Manager()
    result_dict = process_manager.dict()
    urls = ["http://www.baidu.com", "http://www.zhihu.com"]
    reqs = [multiprocessing.Process(target=req_multi, args=(i, result_dict)) for i in urls]
    [j.start() for j in reqs]
    [j.join() for j in reqs]
    print(result_dict)

結果
![image.png](https://upload-images.jianshu.io/upload_images/1500770-b608536e103201be.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

threadingは結果を返す


queueの方式
q = queue.Queue()

def req_threading(url: str):
    r = requests.get(url)
    q.put({url: r})

def main_threading_queue():
    urls = ["http://www.baidu.com", "http://www.zhihu.com"]
    results = [threading.Thread(target=req_threading, args=(i,)) for i in urls]
    [j.start() for j in results]
    [k.join() for k in results]
    while q:
        print(q.get())


classパッケージ方式
class MainThread(threading.Thread):
    def __init__(self, fn_name: str, url: list):
        super(MainThread, self).__init__()
        self.fn_name = fn_name
        self.url = url
        self.result = {}

    def run(self):
        for i in self.url:
            r = requests.get(i)
            self.result[self.fn_name] = r


非同期方式futures

def main_future():
    urls = ["http://www.baidu.com", "http://www.zhihu.com"]
    pool = concurrent.futures.ProcessPoolExecutor(max_workers=2)
    results = [pool.submit(req_futrue, i) for i in urls]
    # results = [pool.map(req_futrue, urls)]
    r = [i.result(timeout=10) for i in  results]
    print(r)


asyncio

import gevent
from gevent import socket
# from gevent import monkey; monkey.patch_all()
import time
start_time = time.time()


async def main_gevnet():

    urls = ["http://www.baidu.com", "http://www.baidu.com"]
    # jobs_1 = [gevent.spawn(req_1, i )for i in urls]
    # jobs_2 = [gevent.spawn(req_2, i )for i in urls]
    # for j in jobs_1:
    #     j.start()
    #     j.join()
    # for k in jobs_2:
    #     k.start()
    #     k.join()
    job_1 = req_1("http://www.baidu.com")
    job_2 = req_2("http://www.baidu.com")

import asyncio
for i in range(100):
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main_gevnet())
print(time.time() - start_time)

gevent

import gevent
from gevent import socket
# from gevent import monkey; monkey.patch_all()
import time
start_time = time.time()


async def main_gevnet():

    urls = ["http://www.baidu.com", "http://www.baidu.com"]
    jobs_1 = [gevent.spawn(req_1, i )for i in urls]
    jobs_2 = [gevent.spawn(req_2, i )for i in urls]
    for j in jobs_1:
        j.start()
        j.join()
    for k in jobs_2:
        k.start()
        k.join()
    # job_1 = req_1("http://www.baidu.com")
    # job_2 = req_2("http://www.baidu.com")