asgi-server-timing-middleware icon indicating copy to clipboard operation
asgi-server-timing-middleware copied to clipboard

SQLAlchemy async

Open antont opened this issue 3 years ago • 4 comments
trafficstars

Hi - would someone know how to profile async SQLAlchemy operations with this?

This works in the sense that I get to see something, but the timing is always ~1ms, maybe because that's how quickly the initial call to the coroutine returns?

  "db_async_exec": (sqlalchemy.ext.asyncio.AsyncSession.execute,),

I also tried to add equivalents to the ResultProxy examples, but these are not correct, don't show up in the timings at all, probably these are just wrong functions.

  "db_async_fetch": (
      sqlalchemy.ext.asyncio.AsyncResult.fetchone,
      sqlalchemy.ext.asyncio.AsyncResult.fetchmany,
  )```

antont avatar Sep 20 '22 08:09 antont

maybe because that's how quickly the initial call to the coroutine returns?

Coroutines are profiled like regular function calls: from function enter to exit. There is no concept of initial call or something like that. See https://github.com/sumerc/yappi/blob/master/doc/coroutine-profiling.md for details.

but the timing is always ~1ms,

Are you sure it is supposed to be greater?

don't show up in the timings at all, probably these are just wrong functions.

To make sure if these functions are called, you could simply profile the whole application without the middleware and see the functions. You can do it either via cProfile or yappi

sumerc avatar Sep 20 '22 09:09 sumerc

Hi, and thanks a lot for the help @sumerc !

Just for info, I was able to profile the whole app with yappi, by hooking the get stats functions in a shutdown event handler, am using FastAPI (failed to mention that earlier).

@app.on_event("shutdown")
def on_shutdown():
    print("SHUTDOWN")
    yappi.get_func_stats().print_all()
    yappi.get_thread_stats().print_all()

The output from there is attached here, yappi_wall-fastapi_asyncpg.txt

I'll study further how to hook individual functions there, or other ways to profile this meaningfully, and proceed to work with this middleware later again then.

antont avatar Sep 22 '22 12:09 antont

Glad it worked! Your current plan makes sense.

sumerc avatar Sep 22 '22 13:09 sumerc

嗨 - 有人知道如何用这个来分析异步 SQLAlchemy 操作吗?

这在我看到一些东西的意义上是有效的,但时间总是〜1ms,也许是因为这就是对协程的初始调用返回的速度有多快?

  "db_async_exec": (sqlalchemy.ext.asyncio.AsyncSession.execute,),

我还尝试在ResultProxy示例中添加等效项,但这些都不正确,根本不会出现在计时中,可能这些只是错误的功能。

  "db_async_fetch": (
      sqlalchemy.ext.asyncio.AsyncResult.fetchone,
      sqlalchemy.ext.asyncio.AsyncResult.fetchmany,
  )```

The fetch operation using asynchronous sqlalchemy to fetch data should be using

from sqlalchemy.engine.result import ChunkedIteratorResult
"db_async_fetch": (
                        ChunkedIteratorResult.scalars,
                        ChunkedIteratorResult.first,
                        .....
                    )

It is because sqlalchemy gets a CkedIteratorResult instead of AsyncResult after execution

pcorvoh avatar Oct 10 '22 01:10 pcorvoh