如何测量异步发电机所花费的时间?

2024-05-07

我想测量生成器花费的时间(阻塞主循环的时间)。

假设我有以下两个生成器:

async def run():
    for i in range(5):
        await asyncio.sleep(0.2)
        yield i
    return

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

我想测量一下run花费了周围0.0s每次迭代,同时walk至少使用过0.3s.

我想用类似的东西this https://stackoverflow.com/questions/73028924/how-to-measure-time-spent-in-blocking-code-while-using-asyncio-in-python,但无法让它为我工作。

澄清:

我想排除花在任何事情上的时间await部分。如果由于任何原因协程被停止,那么我不想考虑这个时间。


所以 - 一件事(虽然有点)是测量常规协同例程中的时间 - 我用装饰器来完成它。

然而,当你进一步进入异步生成器时,它是另一个野兽 - 我仍在试图弄清楚 - 它是公开公开的异步迭代器方法的混合(__anext__, asend等...)在返回的对象中使用传统的迭代器方法,我还无法弄清楚(我刚刚打开 PEP 525 看看我是否能理解它)。

至于常规的协同例程,有一个问题:如果你创建一个可等待的类(我的装饰器),asyncio 将要求其__await__方法返回带有 a 的内容__next__方法,该方法将被调用。但原生 Python 协程没有__next__:异步调用send()在这些上 - 所以我必须进行“转置”以便能够测量时间(在协同例程中)。

import asyncio
import time


class ProfileCoro:
    def __init__(self, corofunc):
        self.corofunc = corofunc

    def __call__(self, *args, **kw):
        # WARNING: not parallel execution-safe: fix by
        # keeping "self.ellapsed" in a proper contextvar
        self.ellapsed = 0
        self.coro = self.corofunc(*args, **kw)
        return self

    def __await__(self):
        return self

    def __iter__(self):
        return self

    def __next__(self):
        return self.send(None)

    def throw(self, exc):
        print(f"Arghh!, got an {exc}")
        self.coro.throw(exc)

    def send(self, arg):
        start = time.monotonic()
        try:
            result = self.coro.send(arg)
        except StopIteration:
            duration = time.monotonic() - start
            self.ellapsed += duration
            print(f"Ellapsed time in execution of {self.corofunc.__name__}: {self.ellapsed:.05f}s")
            raise
        duration = time.monotonic() - start
        self.ellapsed += duration
        return result

    def __repr__(self):
        return f"<ProfileCoro wrapper for {self.corofunc}>"

@ProfileCoro
async def run():
    for i in range(5):
        await asyncio.sleep(0.2)
        # yield i
    return 1

@ProfileCoro
async def walk():
    for i in range(5):
        time.sleep(0.3)
        #yield i
    return 3


async def main():
    await run()
    await walk()
    return

asyncio.run(main())

To maybe如果我能弄清楚如何包装异步生成器,请继续。

(我认为大多数现有的分析工具都使用该语言中可用的工具来进行调试器和跟踪(通过sys.settrace():一切都在回调中“可见”,并且不用担心包装异步机制和异步循环发出的所有内部调用)

... 因此,这里是用于捕获异步生成器中的时间的代码。

它将得到幸福的道路 - 如果有复杂的等待类,实现或利用asend, athrow,这不行 - 但对于一个简单的异步生成器函数插件来说async for声明它现在有效:

免责声明:下面的代码中可能有未使用的代码,甚至未使用的状态 - 我来回了相当多的时间来让它工作(其中很多是因为我没有尝试过这一事实)__anext__本身必须是异步的)。尽管如此,事情还是这样:

import asyncio
import time

from functools import wraps


async def _a():
    yield 1

async_generator_asend_type = type(_a().__anext__())


class ProfileCoro:
    def __init__(self, corofunc):
        self.corofunc = corofunc
        self.measures = 0

    def measure_ellapsed(func):
        @wraps(func)
        def wrapper(self, *args, **kw):
            self.measures += 1
            if self.measures > 1:
                try:
                    return func(self, *args, **kw)
                finally:
                    self.measures -= 1
            start = time.monotonic()
            try:
                result = func(self, *args, **kw)
            except (StopIteration, StopAsyncIteration):
                self.ellapsed += time.monotonic() - start
                #self.print_ellapsed()
                raise
            finally:
                self.measures -= 1
            self.ellapsed += time.monotonic() - start

            return result
        return wrapper

    def print_ellapsed(self):
        name = getattr(self.corofunc, "__name__", "inner_iterator")
        print(f"Ellapsed time in execution of {name}: {self.ellapsed:.05f}s")

    def __call__(self, *args, **kw):
        # WARNING: not parallel execution-safe: fix by
        # keeping "self.ellapsed" in a proper contextvar
        self.ellapsed = 0
        self.measures = 0
        if not isinstance(self.corofunc, async_generator_asend_type):
            self.coro = self.corofunc(*args, **kw)
        else:
            self.coro = self.corofunc
        return self


    def __await__(self):
        return self

    def __iter__(self):
        return self

    @measure_ellapsed
    def __next__(self):
        target = self.coro
        if hasattr(target, "__next__"):
            return target.__next__()
        elif hasattr(target, "send"):
            return target.send(None)

    async def athrow(self, exc):
        print(f"Arghh!, got an async-iter-mode {exc}")
        return await self.async_iter.athrow(exc)

    def throw(self, exc):
        print(f"Arghh!, got an {exc}")
        self.coro.throw(exc)

    @measure_ellapsed
    def send(self, arg):
        return self.coro.send(arg)

    def __aiter__(self):
        return self

    #async def asend(self, value):
        ...

    async def aclose(self):
        return await self.async_iter.close()

    def close(self):
        return self.async_iter.close()

    async def __anext__(self):
        if not hasattr(self, "async_iter"):
            self.async_iter = aiter(self.coro)
        self.inner_profiler = ProfileCoro(self.async_iter.__anext__())
        #start = time.monotonic()
        try:
            result = await self.inner_profiler()
        except StopAsyncIteration:
            #self.print_ellapsed()
            raise
        finally:
            self.ellapsed += self.inner_profiler.ellapsed
        return result

    def __repr__(self):
        return f"<ProfileCoro wrapper for {self.corofunc}>"

@ProfileCoro
async def run():
    for i in range(5):
        await asyncio.sleep(0.05)
        # yield i
    return 1

@ProfileCoro
async def walk():
    for i in range(5):
        time.sleep(0.05)
        #yield i
    return 3


@ProfileCoro
async def irun():
    for i in range(5):
        await asyncio.sleep(0.05)
        yield i

@ProfileCoro
async def iwalk():
    for i in range(5):
        time.sleep(0.05)
        yield i


async def main():
    await run()
    run.print_ellapsed()
    await walk()
    walk.print_ellapsed()
    async for _ in irun():
        print(".", end="", flush=True)
    irun.print_ellapsed()
    async for _ in iwalk():
        pass
    iwalk.print_ellapsed()
    return

asyncio.run(main())

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何测量异步发电机所花费的时间? 的相关文章

随机推荐

  • .net 4.5.1 ASP.NET MVC 5 中的用户锁定

    因此 在新的 Net Framework 4 5 1 AspNetUser 表中没有用于在有限次数的不成功尝试后将用户锁定的列 是否有为此目的构建的框架或解决方案来取代以前的 net 框架中曾经存在的功能 还是我必须自己构建 在即将发布的
  • 如何使用 Windows forfiles 命令的完整路径运行命令?

    我正在尝试运行以下命令 forfiles p Schemas m xsd c cmd c C Program Files x86 Microsoft SDKs Windows v10 0A bin NETFX 4 6 1 Tools xsd
  • 如何在 AWS Elastic Beanstalk 上配置 WSGI 应用程序的名称?

    我的 Python Web 应用程序称为app example py import flask app flask Flask name split 0 当我尝试使用 AWS EB 启动它时 run py set correctly wit
  • 如何在 C# 中将 excel ListObject 添加到给定工作表?

    我目前正在 C 中开发一个 Excel 插件 其中包含多种方法 表值函数 可供 Excel 用户和程序员 VBA 使用 如何编写一个方法 将新的 ListObject Excel 表 添加到给定的 Excel 工作表 并将给定的 DataT
  • Socket.IO 消息不更新 Angular 变量

    我有一个 socket io 客户端 服务器设置 并在客户端上运行 AngularJS Server js var io require socket io server io on connection function socket s
  • ggplot2:为什么半透明+ pdflatex 会导致比普通 PDF 字体更重?

    ggplot2 为什么半透明 pdflatex 会导致比普通 PDF 字体更重 我遇到了一个问题pdf 在 R 中输入 然后pdflatex ing ggplot2 图像会导致同一页面上的所有文本与图像变得粗体 但仅当alpha requi
  • 如何使用蚂蚁?

    我一直试图了解 Ant 的用途 但我仍然不明白 有人可以给我一个使用 Ant 的用例吗 我可以尝试看看 Ant 为何有用以及我可以用它做什么 我在 Eclipse 中进行 Java 开发 并且刚刚开始使用 servlet 和 Google
  • 使用 DOMDocument 进行 PHP 编码

  • mysql_upgrade 失败 - innodb 表不存在?

    我正在将 mysql 5 5 docker 容器数据库升级到 mysql 5 6 docker 容器 我能够解决所有其他问题 最后我的服务器运行的是 5 6 但是当我运行 mysql upgrade 时出现以下错误 ERROR root 1
  • Scala 和 Spark:Windows 上的 Dataframe.write._

    有人设法使用 Spark 写入文件 尤其是 CSV 吗 数据框 http spark apache org docs latest api scala index html org apache spark sql Dataset在 Win
  • java.library.path 中没有 ocijdbc12

    我正在尝试使用 OCI 驱动程序通过 java 程序连接到 oracle 以下是配置 Windows 7 32 位 JDK 1 7 Oracle 客户端 11g R2 ojdbc7 jar在我的独立应用程序的类路径中 但我收到以下异常 Ex
  • AngularJS:在任何部分页面控制器之前调用特定函数

    我想调用一个特定的函数 GetSession 在我的应用程序加载开始时 这个函数使 http调用并获取会话令牌 GlobalSessionToken从服务器 然后 该会话令牌用于其他控制器逻辑并从服务器获取数据 我已经打电话给这个GetSe
  • 无法在 Google Cloud Function 中加载 node_modules(index.js,不在项目根目录上)

    因此 我需要部署 Google Cloud Function 以在 PostgreSQL 数据库 Cloud SQL 上发出选择请求 我需要使用 pg 模块 然后使用以下命令安装它 npm i pg 你需要知道我的项目目录是这样的 proj
  • 添加到 std::vector 的中间

    有没有办法将值添加到 a 的中间vector在 C 中 假设我有 vector
  • 在react中自定义useAxios钩子

    我正在使用 axios 和 React 所以我想为此编写一个自定义钩子 我这样做了 它工作正常 如下所示 const useAxios gt const response setResponse useState const error s
  • 弹性图表隐藏数据提示

    我们从多个源获取数据 并且某个日期的数据可能存在也可能不存在 因此 对于没有数据的点 我们发送 NaN 问题 在下面的代码中 有没有办法不显示那些为空的数据提示 我添加了一个数据提示功能 但它确实显示了一个小的空方块 是否有可能甚至不显示
  • VSCode 扩展的安全性和隐私性

    我发现 VSCode 有很多不错的扩展 然而 我担心这些扩展是否将我的代码发送到他们的任何服务器 有什么办法可以查到吗 我可以使用 fiddler 并隔离插件中可能发生的调用 但不想对我安装的每个扩展都这样做 VScode 团队对此有一些指
  • VS2015 nuget包管理器找不到包

    我安装了 VS2015 Update 2 现在 nuget 包管理器找不到 Microsoft 和 net 包源之外的任何包 看起来 nuget 包源已被删除 当我将其添加回 http www nuget org http www nuge
  • 外部“C”声明如何工作?

    我正在学习编程语言课程 我们正在讨论extern C 宣言 除了 它与 C 和 C 接口 之外 此声明如何在更深层次上工作 这对程序中发生的绑定有何影响 extern C 用于确保后面的符号不是mangled http en wikiped
  • 如何测量异步发电机所花费的时间?

    我想测量生成器花费的时间 阻塞主循环的时间 假设我有以下两个生成器 async def run for i in range 5 await asyncio sleep 0 2 yield i return async def walk f