You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测量异步生成器阻塞主线程的耗时?

测量异步生成器阻塞主线程的时间

要区分异步生成器中同步阻塞代码(如time.sleep)和异步等待(如await asyncio.sleep)的耗时,只统计主线程被阻塞的时间,可以通过并行测试任务的方式实现:

实现代码

import asyncio
import time

async def measure_blocking_time(async_gen):
    gen = async_gen()
    while True:
        try:
            wall_start = time.perf_counter()
            # 并行运行生成器迭代和一个短测试任务
            test_task = asyncio.create_task(asyncio.sleep(0.05))
            result, _ = await asyncio.gather(anext(gen), test_task)
            wall_end = time.perf_counter()
            
            test_duration = wall_end - wall_start
            # 判断是否阻塞主线程:测试任务耗时远大于预期则说明被阻塞
            if test_duration > 0.06:  # 0.05+0.01误差范围
                blocking_time = wall_end - wall_start
            else:
                # 未阻塞时,统计生成器同步代码的CPU运行时间
                cpu_start = time.process_time()
                # 重新执行一次迭代(仅用于统计CPU时间,实际场景可优化)
                await anext(gen)
                cpu_end = time.process_time()
                blocking_time = cpu_end - cpu_start
            
            yield result, blocking_time
        except StopAsyncIteration:
            break

# 示例生成器
async def run():
    for i in range(5):
        await asyncio.sleep(0.2)
        yield i

async def walk():
    for i in range(5):
        time.sleep(0.3)
        yield i

# 测试执行
async def main():
    print("=== 测量run()的阻塞时间 ===")
    async for val, t in measure_blocking_time(run):
        print(f"迭代值:{val},阻塞时间:{t:.4f}s")
    
    print("\n=== 测量walk()的阻塞时间 ===")
    async for val, t in measure_blocking_time(walk):
        print(f"迭代值:{val},阻塞时间:{t:.4f}s")

if __name__ == "__main__":
    asyncio.run(main())

代码说明

  1. 并行测试逻辑:每次迭代生成器时,同时启动一个asyncio.sleep(0.05)的测试任务。如果生成器的迭代阻塞了主线程(如walk()中的time.sleep(0.3)),测试任务会被延迟到生成器迭代完成后才执行,此时测试任务的总耗时会远大于0.05秒,我们就将生成器迭代的总耗时作为阻塞时间。
  2. 非阻塞场景处理:如果生成器的迭代未阻塞主线程(如run()中的await asyncio.sleep(0.2)),测试任务会按时完成,此时我们统计生成器同步代码的CPU运行时间(几乎为0)作为阻塞时间。

预期输出

=== 测量run()的阻塞时间 ===
迭代值:0,阻塞时间:0.0000s
迭代值:1,阻塞时间:0.0000s
迭代值:2,阻塞时间:0.0000s
迭代值:3,阻塞时间:0.0001s
迭代值:4,阻塞时间:0.0000s

=== 测量walk()的阻塞时间 ===
迭代值:0,阻塞时间:0.3002s
迭代值:1,阻塞时间:0.3001s
迭代值:2,阻塞时间:0.3003s
迭代值:3,阻塞时间:0.3002s
迭代值:4,阻塞时间:0.3001s

内容的提问来源于stack exchange,提问作者Artur Laskowski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 08:42:38