【问题标题】:How to profile/benchmark Python ASYNCIO code?如何对 Python ASYNCIO 代码进行分析/基准测试?
【发布时间】:2022-04-22 05:28:10
【问题描述】:

如何对异步 Python 脚本(使用 ASYNCIO)进行分析/基准测试?

你通常会这样做

totalMem = tracemalloc.get_traced_memory()[0]
totalTime = time.time()

retValue = myFunction()

totalTime = time.time() - totalTime 
totalMem = tracemalloc.get_traced_memory()[0] - totalMem 

这样我可以节省函数花费的总时间。 我学会了如何使用装饰器,我就是这么做的 - 并将所有统计数据转储到一个文本文件中以供以后分析。

但是,当您拥有 ASYNCIO 脚本时,情况就大不相同了:该函数将在执行“await aiohttpSession.get()”时阻塞,并且控制将返回到事件循环,该循环将运行其他函数。

这样,经过的时间和总分配内存的变化不会透露任何信息,因为我将测量的不仅仅是那个函数。

唯一可行的方法是

class MyTracer:
  def __init__(self):
    self.totalTime = 0
    self.totalMem = 0
    self.startTime = time.time()
    self.startMem = tracemalloc.get_traced_memory()[0]
  def stop(self):
    self.totalTime += time.time() - self.startTime
    self.totalMem += tracemalloc.get_traced_memory()[0] - self.startMem
  def start(self):
    self.startTime = time.time()
    self.startMem = tracemalloc.get_traced_memory()[0]

现在,不知何故,将其插入代码中:

def myFunction():

    tracer = MyTracer()

    session = aiohttp.ClientSession()

    # do something

    tracer.stop()
    # the time elapsed here, and the changes in the memory allocation, are not from the current function
    retValue = await(await session.get('https://hoochie-mama.org/cosmo-kramer',
        headers={
            'User-Agent': 'YoYo Mama! v3.0',
            'Cookies': 'those cookies are making me thirsty!',
            })).text()
    tracer.start()

    # do more things

    tracer.stop()

    # now "tracer" has the info about total time spent in this function, and the memory allocated by it
    # (the memory stats could be negative if the function releases more than allocates)

有没有办法实现这一点,我的意思是,无需插入所有这些代码就可以分析我的所有 asyncio 代码? 或者是否有一个模块已经能够做到这一点?

【问题讨论】:

    标签: python profiling benchmarking python-asyncio


    【解决方案1】:

    查看支持协程分析的Yappi profilerTheir page on coroutine profiling 非常清楚地描述了您面临的问题:

    协程的主要问题是,当协程产生或换句话说上下文切换时,Yappi 会收到一个返回事件,就像我们退出函数一样。这意味着协程处于屈服状态时所花费的时间不会累积到输出中。这是一个问题,尤其是对于挂墙时间,因为在挂墙时间中,您希望查看在该函数或协程中花费的全部时间。另一个问题是通话次数。您会看到每次协程产生时,调用计数都会增加,因为它是常规函数退出。

    他们还非常高级地描述了 Yappi 如何解决这个问题:

    在 v1.2 中,Yappi 纠正了上述协程分析问题。在底层,它将 yield 与实际函数退出区分开来,如果选择 wall time 作为clock_type,它将累积时间并更正调用计数指标。

    【讨论】:

      猜你喜欢
      • 2014-09-20
      • 1970-01-01
      • 1970-01-01
      • 2013-03-10
      • 2011-01-21
      • 2020-11-25
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多