pythonasyncioapiasyncfastapiframeworkjsonjson-schemaopenapiopenapi3pydanticpython-typespython3redocreststarletteswaggerswagger-uiuvicornweb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.9 KiB
105 lines
2.9 KiB
import time
|
|
|
|
from fastapi import APIRouter, FastAPI
|
|
|
|
# Setup Router
|
|
app = FastAPI()
|
|
router = APIRouter()
|
|
|
|
# 50 Static Routes
|
|
for i in range(50):
|
|
|
|
@router.get(f"/static-{i}")
|
|
def static_route(i=i):
|
|
return {"route": f"static-{i}"}
|
|
|
|
|
|
# 50 Dynamic Routes
|
|
for i in range(50):
|
|
|
|
@router.get(f"/dynamic-{i}/{{item_id}}")
|
|
def dynamic_route(item_id: int, i=i):
|
|
return {"route": f"dynamic-{i}", "item_id": item_id}
|
|
|
|
|
|
app.include_router(router)
|
|
from contextlib import AsyncExitStack
|
|
|
|
import anyio
|
|
|
|
|
|
# Mock ASGI stack
|
|
async def mock_receive():
|
|
return {"type": "http.request", "body": b"", "more_body": False}
|
|
|
|
|
|
async def mock_send(message):
|
|
pass
|
|
|
|
|
|
scope_static = {
|
|
"type": "http",
|
|
"method": "GET",
|
|
"path": "/static-49",
|
|
"headers": [],
|
|
"query_string": b"",
|
|
"client": ("127.0.0.1", 1234),
|
|
"server": ("127.0.0.1", 80),
|
|
"fastapi_middleware_astack": AsyncExitStack(),
|
|
"fastapi_inner_astack": AsyncExitStack(),
|
|
"fastapi_function_astack": AsyncExitStack(),
|
|
}
|
|
|
|
scope_dynamic = {
|
|
"type": "http",
|
|
"method": "GET",
|
|
"path": "/dynamic-49/12345",
|
|
"headers": [],
|
|
"query_string": b"",
|
|
"client": ("127.0.0.1", 1234),
|
|
"server": ("127.0.0.1", 80),
|
|
"fastapi_middleware_astack": AsyncExitStack(),
|
|
"fastapi_inner_astack": AsyncExitStack(),
|
|
"fastapi_function_astack": AsyncExitStack(),
|
|
}
|
|
|
|
|
|
async def run_benchmark():
|
|
# Warmup
|
|
for _ in range(100):
|
|
await app.router.app(dict(scope_static), mock_receive, mock_send)
|
|
await app.router.app(dict(scope_dynamic), mock_receive, mock_send)
|
|
|
|
print("Running Static Route Benchmark (10,000 iterations)...")
|
|
|
|
# 1. Caching Enabled (standard flow)
|
|
# Warmup cache
|
|
await app.router.app(dict(scope_static), mock_receive, mock_send)
|
|
start_time = time.perf_counter()
|
|
for _ in range(10000):
|
|
await app.router.app(dict(scope_static), mock_receive, mock_send)
|
|
cache_enabled_time = time.perf_counter() - start_time
|
|
|
|
# 2. Caching Disabled (clear cache before each request)
|
|
start_time = time.perf_counter()
|
|
for _ in range(10000):
|
|
app.router._route_cache.clear()
|
|
await app.router.app(dict(scope_static), mock_receive, mock_send)
|
|
cache_disabled_time = time.perf_counter() - start_time
|
|
|
|
print(f"Static Route - Cache Enabled: {cache_enabled_time:.4f} seconds")
|
|
print(f"Static Route - Cache Disabled: {cache_disabled_time:.4f} seconds")
|
|
print(f"Speedup: {cache_disabled_time / cache_enabled_time:.2f}x")
|
|
|
|
print("\nRunning Dynamic Route Benchmark (10,000 iterations)...")
|
|
|
|
# Caching has no effect on dynamic routes
|
|
start_time = time.perf_counter()
|
|
for _ in range(10000):
|
|
await app.router.app(dict(scope_dynamic), mock_receive, mock_send)
|
|
dynamic_time = time.perf_counter() - start_time
|
|
print(f"Dynamic Route time: {dynamic_time:.4f} seconds")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
anyio.run(run_benchmark)
|
|
|