Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyperformance/data-files/benchmarks/MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ django_template <local>
dulwich_log <local>
docutils <local>
fannkuch <local>
fastapi <local>
float <local>
genshi <local>
go <local>
Expand Down
15 changes: 15 additions & 0 deletions pyperformance/data-files/benchmarks/bm_fastapi/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[project]
name = "pyperformance_bm_fastapi"
requires-python = ">=3.10"
dependencies = [
"pyperf",
"fastapi",
"uvicorn",
"httpx",
]
urls = {repository = "https://github.com/python/pyperformance"}
dynamic = ["version"]

[tool.pyperformance]
name = "fastapi"
tags = "apps"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fastapi==0.121.0
httpx==0.28.1
uvicorn==0.38.0
87 changes: 87 additions & 0 deletions pyperformance/data-files/benchmarks/bm_fastapi/run_benchmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
Test the performance of simple HTTP serving with FastAPI.

This benchmark tests FastAPI's request handling, including:
- Path parameter extraction and validation
- Pydantic model serialization
- JSON response encoding

The bench serves a REST API endpoint that returns JSON objects,
simulating a typical web application scenario.

Author: Savannah Ostrowski
"""

import asyncio
import socket
import time

import httpx
import pyperf
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel

HOST = "127.0.0.1"

CONCURRENCY = 150

class Item(BaseModel):
id: int
name: str
price: float
tags: list[str] = []

app = FastAPI()

@app.get("/items/{item_id}", response_model=Item)
async def get_item(item_id: int):
return {
"id": item_id,
"name": "Sample Item",
"price": 9.99,
"tags": ["sample", "item", "fastapi"]
}


async def run_server_and_benchmark(loops):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, 0))
s.listen(1)
port = s.getsockname()[1]

config = uvicorn.Config(app, host=HOST, port=port, log_level="error")
server = uvicorn.Server(config)
server_task = asyncio.create_task(server.serve())

await asyncio.sleep(0.5)

async with httpx.AsyncClient() as client:
t0 = time.perf_counter()

for i in range(loops):
tasks = [
client.get(f"http://{HOST}:{port}/items/{i}")
for _ in range(CONCURRENCY)
]
responses = await asyncio.gather(*tasks)
for response in responses:
response.raise_for_status()
data = response.json()
assert data["id"] == i
assert "tags" in data

elapsed = time.perf_counter() - t0

server.should_exit = True
await server_task
return elapsed

def bench_fastapi(loops):
return asyncio.run(run_server_and_benchmark(loops))


if __name__ == "__main__":
runner = pyperf.Runner()
runner.metadata['description'] = "Test the performance of HTTP requests with FastAPI"
runner.bench_time_func("fastapi_http", bench_fastapi)
Loading