Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python asyncio与ThreadPoolExecutor-纯基于I/O的任务的结果不一致_Python_Multithreading_Python Asyncio_Httpx - Fatal编程技术网

Python asyncio与ThreadPoolExecutor-纯基于I/O的任务的结果不一致

Python asyncio与ThreadPoolExecutor-纯基于I/O的任务的结果不一致,python,multithreading,python-asyncio,httpx,Python,Multithreading,Python Asyncio,Httpx,我最近遇到了一个问题,需要尽快获取URL列表 所以很自然地,我设置了一个小测试,看看什么最有效 方法1-异步 async def test_async(): async with httpx.AsyncClient() as client: await asyncio.gather(*(fetch_async(client, symbol) for symbol in symbols)) async def fetch_async(client, symbol):

我最近遇到了一个问题,需要尽快获取URL列表

所以很自然地,我设置了一个小测试,看看什么最有效


方法1-异步

async def test_async():
    async with httpx.AsyncClient() as client:
        await asyncio.gather(*(fetch_async(client, symbol) for symbol in symbols))


async def fetch_async(client, symbol):
    await client.get(
        f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}.NS", timeout=None,
    )

方法2-ThreadPoolExecutor

async def test_threads():
    with ThreadPoolExecutor(max_workers=len(symbols)) as pool, httpx.Client() as client:
        loop = asyncio.get_event_loop()

        await asyncio.gather(
            *(
                loop.run_in_executor(pool, fetch_sync_fn(client, symbol))
                for symbol in symbols
            )
        )


def fetch_sync_fn(client, symbol):
    def fn():
        client.get(
            f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}.NS",
            timeout=None,
        )

    return fn

2013年MacBook pro的测试结果

In [3]: %timeit asyncio.run(test_threads())                                                                                                                                                          
1.41 s ± 87.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [4]: %timeit asyncio.run(test_async())                                                                                                                                                            
1.24 s ± 62.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
digital ocean 5$服务器上的结果

In [4]: %timeit asyncio.run(test_threads())
5.94 s ± 66.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [3]: %timeit asyncio.run(test_async())
10.7 s ± 97.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
结果在一个


问题

  • 这种不一致的原因是什么?为什么在服务器和本地机器上有不同的赢家
  • 为什么服务器上的两个测试都比较慢?在具有更快网络连接的服务器上,纯网络任务不应该更快吗


  • 如果您的Droplet有一个共享的CPU,那么您将在CPU时间上与比您自己的进程更多的进程竞争。但这不是一个CPU受限的任务,为什么CPU在这种情况下会成为瓶颈?另外,我想补充一点,您正在使用一个公共url。这可能会受到其他用户流量的影响,这可能会改变响应的时间。最后一件事:通过使用
    async with httpx.AsyncClient()
    ,您只需第一次连接,并将连接重新用于其他请求,而对于线程,您可以从头开始在每个请求中连接。@lsabi好的,将线程版本更改为重新使用客户端。它使线程版本更快了,但DO-box测试仍然让我的大脑陷入混乱。我不确定我能对公共URL做些什么。如果有帮助的话,很乐意使用其他东西。
    %timeit loop.run_until_complete(test_threads())
    1 loop, best of 3: 723 ms per loop
    
    %timeit loop.run_until_complete(test_async())
    1 loop, best of 3: 597 ms per loop