mirror of
https://github.com/fastapi/fastapi.git
synced 2026-09-17 16:25:49 -04:00
👷 Add CI memory benchmark (#16046)
This commit is contained in:
1 parent
a64dfbbd21
commit
513c396322
5 files changed
+95
-3
No files matched your search
@@ -195,6 +195,11 @@ jobs:
|
||||
with:
|
||||
mode: simulation
|
||||
run: uv run --no-sync pytest tests/benchmarks --codspeed
|
||||
- name: CodSpeed memory benchmark
|
||||
uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1
|
||||
with:
|
||||
mode: memory
|
||||
run: uv run --no-sync pytest tests/memory_benchmarks --codspeed
|
||||
|
||||
coverage-combine:
|
||||
needs:
|
||||
|
||||
+2
-1
@@ -168,7 +168,7 @@ tests = [
|
||||
"pwdlib[argon2] >=0.2.1",
|
||||
"pyjwt >=2.9.0",
|
||||
"pytest >=9.0.0",
|
||||
"pytest-codspeed >=4.2.0",
|
||||
"pytest-codspeed >=4.3.0",
|
||||
"pyyaml >=5.3.1,<7.0.0",
|
||||
"sqlmodel >=0.0.31",
|
||||
"strawberry-graphql >=0.200.0,<1.0.0",
|
||||
@@ -244,6 +244,7 @@ relative_files = true
|
||||
context = '${CONTEXT}'
|
||||
omit = [
|
||||
"tests/benchmarks/*",
|
||||
"tests/memory_benchmarks/*",
|
||||
"docs_src/response_model/tutorial003_04_py310.py",
|
||||
"docs_src/dependencies/tutorial013_an_py310.py", # temporary code example?
|
||||
"docs_src/dependencies/tutorial014_an_py310.py", # temporary code example?
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,86 @@
|
||||
import inspect
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
if "--codspeed" not in sys.argv:
|
||||
pytest.skip(
|
||||
"Benchmark tests are skipped by default; run with --codspeed.",
|
||||
allow_module_level=True,
|
||||
)
|
||||
|
||||
LAST_DEPENDENCY_INDEX = 100
|
||||
ENDPOINT_PARAMETER_COUNT = 50
|
||||
ROUTE_PATH = "/dynamic-health"
|
||||
|
||||
|
||||
def _create_app() -> FastAPI:
|
||||
app = FastAPI()
|
||||
dependencies: dict[int, Callable[..., Any]] = {}
|
||||
|
||||
def create_dependency(index: int) -> Callable[..., Any]:
|
||||
if index == LAST_DEPENDENCY_INDEX:
|
||||
|
||||
def dependency() -> str:
|
||||
return str(index)
|
||||
|
||||
dependency.__name__ = f"dependency_{index}"
|
||||
return dependency
|
||||
|
||||
next_dependency = dependencies[index + 1]
|
||||
|
||||
async def dependency(
|
||||
sub_dependency: str = Depends(next_dependency),
|
||||
) -> str:
|
||||
return f"{index} -> {sub_dependency}"
|
||||
|
||||
dependency.__name__ = f"dependency_{index}"
|
||||
return dependency
|
||||
|
||||
for index in reversed(range(LAST_DEPENDENCY_INDEX + 1)):
|
||||
dependencies[index] = create_dependency(index)
|
||||
|
||||
def create_endpoint() -> Callable[..., Any]:
|
||||
parameters = [
|
||||
inspect.Parameter(
|
||||
name=f"arg_{index}",
|
||||
kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
||||
default=Depends(dependencies[index]),
|
||||
annotation=str,
|
||||
)
|
||||
for index in range(ENDPOINT_PARAMETER_COUNT)
|
||||
]
|
||||
|
||||
async def endpoint(**kwargs: str) -> dict[str, int]:
|
||||
return {"parameter_count": len(kwargs)}
|
||||
|
||||
endpoint_with_signature: Any = endpoint
|
||||
endpoint_with_signature.__signature__ = inspect.Signature(parameters)
|
||||
return endpoint
|
||||
|
||||
for method in ("GET", "POST"):
|
||||
app.add_api_route(
|
||||
ROUTE_PATH,
|
||||
create_endpoint(),
|
||||
methods=[method],
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def test_dependency_graph(benchmark) -> None:
|
||||
app = benchmark(_create_app)
|
||||
dynamic_routes = [
|
||||
route
|
||||
for route in app.routes
|
||||
if isinstance(route, APIRoute) and route.path == ROUTE_PATH
|
||||
]
|
||||
assert len(dynamic_routes) == 2
|
||||
assert {method for route in dynamic_routes for method in route.methods} == {
|
||||
"GET",
|
||||
"POST",
|
||||
}
|
||||
@@ -1064,7 +1064,7 @@ dev = [
|
||||
{ name = "pygithub", specifier = ">=2.8.1" },
|
||||
{ name = "pyjwt", specifier = ">=2.9.0" },
|
||||
{ name = "pytest", specifier = ">=9.0.0" },
|
||||
{ name = "pytest-codspeed", specifier = ">=4.2.0" },
|
||||
{ name = "pytest-codspeed", specifier = ">=4.3.0" },
|
||||
{ name = "pytest-cov", specifier = ">=4.0.0" },
|
||||
{ name = "pytest-sugar", specifier = ">=1.0.0" },
|
||||
{ name = "pytest-timeout", specifier = ">=2.4.0" },
|
||||
@@ -1124,7 +1124,7 @@ tests = [
|
||||
{ name = "pwdlib", extras = ["argon2"], specifier = ">=0.2.1" },
|
||||
{ name = "pyjwt", specifier = ">=2.9.0" },
|
||||
{ name = "pytest", specifier = ">=9.0.0" },
|
||||
{ name = "pytest-codspeed", specifier = ">=4.2.0" },
|
||||
{ name = "pytest-codspeed", specifier = ">=4.3.0" },
|
||||
{ name = "pytest-cov", specifier = ">=4.0.0" },
|
||||
{ name = "pytest-sugar", specifier = ">=1.0.0" },
|
||||
{ name = "pytest-timeout", specifier = ">=2.4.0" },
|
||||
|
||||
Reference in new issue
Block a user