Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 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
89 changes: 89 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,89 @@
"""
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 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"]
}


def bench_fastapi(loops, url):
async def run_benchmark():
async with httpx.AsyncClient() as client:
t0 = pyperf.perf_counter()

for i in range(loops):
tasks = [
client.get(f"{url}/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

return pyperf.perf_counter() - t0

return asyncio.run(run_benchmark())


if __name__ == "__main__":
import threading

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_thread = threading.Thread(target=server.run, daemon=True)
server_thread.start()

while not server.started:
pass

url = f"http://{HOST}:{port}"

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