FastAPI のパフォーマンス分析
Python で WebAPI を開発する際は、個人的に FastAPI を使うことが多い。WebAPI のパフォーマンスをチューニングしたい場面が何度かあり、そのためのプロファイリング方法を調べたので備忘録として残しておく。
プロファイリングの方法
私が観測している範囲では、次のようなツールでプロファイリングできる。
今回メインで取り上げるのは fastapi_profiler
である。他の 2 つについて軽く触れておくと、logfire
は pydantic チームが開発しているサービス。logfire のサービスに OpenTelemetry を使ってデータを送信することで、リクエストのトレースができる。 Pydantic との統合や FastAPI 以外にも OpenAI のフレームワークとも連携できる。2024/05/03 時点ではベータ版となっており無料で利用できる。 OpenTelemetry
は、分散トレーシングのためのプロジェクトで、FastAPI にも導入できる。各クラウドプロバイダーのサービスとも連携できる。
fastapi_profiler
fastapi_profiler
は FastAPI 用のプロファイリングツールで、FastAPI のリクエストに対してプロファイリングできる。リクエストごとの処理時間やメモリ使用量、各 Python コードの処理時間を計測できる。FastAPI のミドルウェアとして機能する。
インストール
| pip install fastapi_profiler
|
使い方
FastAPI のミドルウェアとして PyInstrumentProfilerMiddleware
を追加するだけで利用できる。
| import time
import uvicorn
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi_profiler import PyInstrumentProfilerMiddleware
app = FastAPI()
app.add_middleware(PyInstrumentProfilerMiddleware)
@app.get("/test")
async def normal_request():
time.sleep(1)
return JSONResponse({"retMsg": "Hello World!"})
if __name__ == '__main__':
uvicorn.run(app=app, host="0.0.0.0", port=8080, workers=1)
|
/test
にリクエストを送信すると、次のようなログが出力される。
| INFO: 127.0.0.1:54872 - "GET /test HTTP/1.1" 200 OK
Method: GET, Path: /test, Duration: 1.0088946190662682, Status: 200
_ ._ __/__ _ _ _ _ _/_ Recorded: 07:11:39 Samples: 83
/_//_/// /_\ / //_// / //_'/ // Duration: 1.009 CPU time: 0.009
/ _/ v4.6.2
Program: /tmp/pants-sandbox-ETDYpC/sandbox/fastapi-profiler/app.py
1.009 PyInstrumentProfilerMiddleware.__call__ fastapi_profiler/profiler.py:66
`- 1.009 ExceptionMiddleware.__call__ starlette/middleware/exceptions.py:49
[10 frames hidden] starlette, fastapi
1.001 run_endpoint_function fastapi/routing.py:183
`- 1.001 normal_request sandbox/fastapi-profiler/app.py:14
`- 1.000 sleep <built-in>
|
今回の例は簡単なものだが、複雑な処理を行っている場合は、各関数や行レベルで計測してくれるので、ボトルネックを特定するのに便利。 設定次第で html や json で出力することもできる。
余談
この middleware を有効にしてリクエストを繰り返すと段々処理が遅くなる。利用の際は注意が必要。