Skip to content

Commit c41ffc7

Browse files
[PR #10095/fcce1bf6 backport][3.11] Add a benchmark for web.FileResponse (#10097)
**This is a backport of PR #10095 as merged into master (fcce1bf).** We didn't have any benchmarks for file responses. From the benchmarks it turns out most of the time is creating and processing the executor jobs. If we combine the stat into a job that returns the open fileobj it will likely be faster and solve #8013 Co-authored-by: J. Nick Koston <nick@koston.org>
1 parent 86bb6ad commit c41ffc7

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""codspeed benchmarks for the web file responses."""
2+
3+
import asyncio
4+
import pathlib
5+
6+
from pytest_codspeed import BenchmarkFixture
7+
8+
from aiohttp import web
9+
from aiohttp.pytest_plugin import AiohttpClient
10+
11+
12+
def test_simple_web_file_response(
13+
loop: asyncio.AbstractEventLoop,
14+
aiohttp_client: AiohttpClient,
15+
benchmark: BenchmarkFixture,
16+
) -> None:
17+
"""Benchmark creating 100 simple web.FileResponse."""
18+
response_count = 100
19+
filepath = pathlib.Path(__file__).parent / "sample.txt"
20+
21+
async def handler(request: web.Request) -> web.FileResponse:
22+
return web.FileResponse(path=filepath)
23+
24+
app = web.Application()
25+
app.router.add_route("GET", "/", handler)
26+
27+
async def run_file_resonse_benchmark() -> None:
28+
client = await aiohttp_client(app)
29+
for _ in range(response_count):
30+
await client.get("/")
31+
await client.close()
32+
33+
@benchmark
34+
def _run() -> None:
35+
loop.run_until_complete(run_file_resonse_benchmark())
36+
37+
38+
def test_simple_web_file_sendfile_fallback_response(
39+
loop: asyncio.AbstractEventLoop,
40+
aiohttp_client: AiohttpClient,
41+
benchmark: BenchmarkFixture,
42+
) -> None:
43+
"""Benchmark creating 100 simple web.FileResponse without sendfile."""
44+
response_count = 100
45+
filepath = pathlib.Path(__file__).parent / "sample.txt"
46+
47+
async def handler(request: web.Request) -> web.FileResponse:
48+
transport = request.transport
49+
assert transport is not None
50+
transport._sendfile_compatible = False # type: ignore[attr-defined]
51+
return web.FileResponse(path=filepath)
52+
53+
app = web.Application()
54+
app.router.add_route("GET", "/", handler)
55+
56+
async def run_file_resonse_benchmark() -> None:
57+
client = await aiohttp_client(app)
58+
for _ in range(response_count):
59+
await client.get("/")
60+
await client.close()
61+
62+
@benchmark
63+
def _run() -> None:
64+
loop.run_until_complete(run_file_resonse_benchmark())

0 commit comments

Comments
 (0)