Skip to content

🔖 0.6.0 - Supporting Profiling

Compare
Choose a tag to compare
@yezz123 yezz123 released this 23 Jul 00:57
· 976 commits to main since this release
47a0af9

Idea

Profiling is a technique to figure out how time is spent in a program. With
these statistics, we can find the “hot spot” of a program and think about ways
of improvement. Sometimes, a hot spot in an unexpected location may also hint at
a bug in the program.

Pyinstrument is a Python profiler. A profiler is a tool to help you optimize
your code - make it faster.

Profile a web request in FastAPI

To profile call stacks in FastAPI, you can write a middleware extension for
pyinstrument.

Create an async function and decorate it with app.middleware('http') where the
app is the name of your FastAPI application instance.

Make sure you configure a setting to only make this available when required.

from pyinstrument import Profiler
PROFILING = True  # Set this from a settings model
if PROFILING:
    @app.middleware("http")
    async def profile_request(request: Request, call_next):
        profiling = request.query_params.get("profile", False)
        if profiling:
            profiler = Profiler(interval=settings.profiling_interval, async_mode="enabled")
            profiler.start()
            await call_next(request)
            profiler.stop()
            return HTMLResponse(profiler.output_html())
        else:
            return await call_next(request)

To invoke, make any request to your application with the GET parameter
profile=1 and it will print the HTML result from pyinstrument.

AuthX's Support

With AuthX the abstract of profiling is easy, it's just about calling the
ProfilerMiddleware 's class and calling it in
add_middleware(ProfilerMiddleware) func that FastAPI provides.

Example

import os
import uvicorn
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from authx import ProfilerMiddleware
app = FastAPI()
app.add_middleware(ProfilerMiddleware)
@app.get("/test")
async def normal_request():
    return JSONResponse({"retMsg": "Hello World!"})
if __name__ == '__main__':
    app_name = os.path.basename(__file__).replace(".py", "")
    uvicorn.run(app=f"{app_name}:app", host="0.0.0.0", port=8080, workers=1)

References

What's Changed

  • 👷 Support Profiling for checking service performance by @yezz123 in #240
  • 👷 chore(fix): Fix Failed tests for Oauth2 by @yezz123 in #241
  • 🔖 Clean codebase from unread Docstrings by @yezz123 in #242
  • 📝 Docs: Upgrade pre-commit and add new markdown's linter by @yezz123 in #243
  • 🔧 Upgrade all Github Actions by @yezz123 in #249
  • Chore(deps): Bump jsmrcaga/action-netlify-deploy from 1.1.0 to 1.8.0 by @dependabot in #250
  • Add license scan report and status by @fossabot in #253
  • 🔖 release 0.6.0 - Supporting Profiling by @yezz123 in #255

New Contributors

Full Changelog: 0.5.1...0.6.0