【问题标题】:How to determine the optimal amount of buffer size with asyncio/aiohttp如何使用 asyncio/aiohttp 确定最佳缓冲区大小
【发布时间】:2023-03-24 05:40:01
【问题描述】:

在 python 中使用 asyncio 时,我们如何确定 read() 的最佳参数? 12 字节? 100 字节?

async with self._session.get(url, headers=headers) as response:
    chunk_size = 12
    result = ''

    while True:
       chunk = await response.content.read(chunk_size)
          if not chunk:
              break
          elif isinstance(chunk, (bytes, bytearray)):
              data = chunk.decode('utf8')
               result += data

【问题讨论】:

    标签: python python-asyncio aiohttp


    【解决方案1】:

    在 python 中使用 asyncio 时,我们如何确定 read() 的最佳参数? 12 字节? 100 字节?

    您可以放心地选择比这大得多的数字。如果数字太小(例如只有 1),您的循环将包含对 StreamReader.read 的许多调用,每个调用都带有固定的开销 - 它必须检查缓冲区中是否有东西,或者返回一部分那并更新剩余的缓冲区,或等待新的东西到达。另一方面,如果请求的大小过大,理论上它可能需要不必要的大分配。但由于StreamReader.read 允许返回比指定更少的数据,它永远不会返回大于内部缓冲区(64 KiB by default)的块,所以这不是问题。

    总结:任何大于 1024 的数字都可以,因为它足够大,可以避免不必要的函数调用次数。在大多数情况下,请求超过 65536 与请求 65536 相同。当我不关心绝对最佳性能时,我倾向于请求 1024 字节(调试时较小的块更容易让人眼前一亮),而当我使用较大的值时,例如 16384做。这些数字不必是 2 的幂,顺便说一句,这只是来自更底层语言的约定。

    当专门处理aiohttp流时,你可以调用readany,这个方法只返回任何可用的数据,如果没有可用的数据,则等待一些数据到达并返回。如果您正在处理 aiohttp 流,这可能是最好的选择,因为它只是为您提供来自内部缓冲区的数据,而不必怀疑其大小。

    【讨论】:

    • 超级有用的答案!我检查了 asyncio/streams.py 中的缓冲区限制,您介意更新您的答案吗:_DEFAULT_LIMIT = 2 ** 16 # 64 KiB
    • 另外,您的直觉是从同一进程中的缓冲区中读取(2**16)或readany()足够快,可以在单个协程中运行(打破现实世界没有好处小块)?
    • @v1z3 很好,我现在更正了默认缓冲区大小值。我不确定您所说的“足够快以在单个协程中运行”是什么意思 - 您无法通过从多个协程中读取相同的流来加快速度。
    • @v1z3 在大多数代码中,我看不到人为创建比实际从网络接收到的更小的块有什么好处。如果代码确实出于某些特定领域的原因需要更小的块,那么从 asyncio 开始请求这些块肯定是有意义的并且更有效。但是这样的代码在恕我直言非常罕见,典型的代码要么不关心块大小(例如您问题中的代码),要么对块有更具体的要求(例如它以换行符或 EOF 结尾,如提供readline())。
    • 谢谢!我做了一些基准测试并回答了我自己的推测性问题。
    猜你喜欢
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 2010-12-05
    • 2012-02-06
    相关资源
    最近更新 更多