11"""codspeed benchmarks for HTTP client."""
22
33import asyncio
4- from collections .abc import Iterator
5- from typing import TYPE_CHECKING , Any
4+ import ssl
5+ from collections .abc import Awaitable , Callable , Iterator
6+ from dataclasses import dataclass
7+ from typing import TYPE_CHECKING , Any , TypedDict
68
79import pytest
810from pytest_aiohttp import AiohttpClient , AiohttpServer
911from yarl import URL
1012
1113from aiohttp import hdrs , request , web
12- from aiohttp .test_utils import TestServer
14+ from aiohttp .test_utils import TestClient , TestServer
1315
1416if TYPE_CHECKING :
1517 from pytest_codspeed import BenchmarkFixture
1820 BenchmarkFixture = pytest_codspeed .BenchmarkFixture
1921
2022
23+ @pytest .fixture
24+ def aiohttp_client_sync (
25+ event_loop : asyncio .AbstractEventLoop ,
26+ ) -> Iterator [
27+ Callable [[web .Application ], Awaitable [TestClient [web .Request , web .Application ]]]
28+ ]:
29+ clients = []
30+
31+ async def go (
32+ app : web .Application ,
33+ * ,
34+ server_kwargs : dict [str , Any ] | None = None ,
35+ ) -> TestClient [web .Request , web .Application ]:
36+ server = TestServer (app )
37+ client = TestClient (server )
38+ await server .start_server (** (server_kwargs or {}))
39+ await client .start_server ()
40+ clients .append (client )
41+ return client
42+
43+ yield go
44+
45+ while clients :
46+ event_loop .run_until_complete (clients .pop ().close ())
47+
48+
49+ class _ConnArgs (TypedDict , total = False ):
50+ ssl : ssl .SSLContext
51+
52+
53+ @dataclass (frozen = True )
54+ class ConnectionType :
55+ s_kwargs : _ConnArgs
56+ c_kwargs : _ConnArgs
57+
58+
59+ @pytest .fixture (params = ("tcp" , "ssl" ), ids = ("tcp" , "ssl" ))
60+ def conn_type (
61+ request : pytest .FixtureRequest ,
62+ ssl_ctx : ssl .SSLContext ,
63+ client_ssl_ctx : ssl .SSLContext ,
64+ ) -> ConnectionType :
65+ if request .param == "ssl" :
66+ return ConnectionType (
67+ s_kwargs = {"ssl" : ssl_ctx },
68+ c_kwargs = {"ssl" : client_ssl_ctx },
69+ )
70+ return ConnectionType (s_kwargs = {}, c_kwargs = {})
71+
72+
2173@pytest .fixture
2274def aiohttp_server_sync (
2375 event_loop : asyncio .AbstractEventLoop ,
@@ -45,8 +97,9 @@ async def go(
4597
4698def test_one_hundred_simple_get_requests (
4799 event_loop : asyncio .AbstractEventLoop ,
48- aiohttp_client : AiohttpClient ,
100+ aiohttp_client_sync : AiohttpClient ,
49101 benchmark : BenchmarkFixture ,
102+ conn_type : ConnectionType ,
50103) -> None :
51104 """Benchmark 100 simple GET requests."""
52105 message_count = 100
@@ -58,9 +111,9 @@ async def handler(request: web.Request) -> web.Response:
58111 app .router .add_route ("GET" , "/" , handler )
59112
60113 async def run_client_benchmark () -> None :
61- client = await aiohttp_client (app )
114+ client = await aiohttp_client_sync (app , server_kwargs = conn_type . s_kwargs )
62115 for _ in range (message_count ):
63- await client .get ("/" )
116+ await client .get ("/" , ** conn_type . c_kwargs )
64117 await client .close ()
65118
66119 @benchmark
@@ -70,7 +123,7 @@ def _run() -> None:
70123
71124def test_one_hundred_simple_get_requests_alternating_clients (
72125 event_loop : asyncio .AbstractEventLoop ,
73- aiohttp_client : AiohttpClient ,
126+ aiohttp_client_sync : AiohttpClient ,
74127 benchmark : BenchmarkFixture ,
75128) -> None :
76129 """Benchmark 100 simple GET requests with alternating clients."""
@@ -83,8 +136,8 @@ async def handler(request: web.Request) -> web.Response:
83136 app .router .add_route ("GET" , "/" , handler )
84137
85138 async def run_client_benchmark () -> None :
86- client1 = await aiohttp_client (app )
87- client2 = await aiohttp_client (app )
139+ client1 = await aiohttp_client_sync (app )
140+ client2 = await aiohttp_client_sync (app )
88141 for i in range (message_count ):
89142 if i % 2 == 0 :
90143 await client1 .get ("/" )
@@ -154,8 +207,9 @@ def _run() -> None:
154207
155208def test_one_hundred_get_requests_with_1024_chunked_payload (
156209 event_loop : asyncio .AbstractEventLoop ,
157- aiohttp_client : AiohttpClient ,
210+ aiohttp_client_sync : AiohttpClient ,
158211 benchmark : BenchmarkFixture ,
212+ conn_type : ConnectionType ,
159213) -> None :
160214 """Benchmark 100 GET requests with a small payload of 1024 bytes."""
161215 message_count = 100
@@ -170,9 +224,9 @@ async def handler(request: web.Request) -> web.Response:
170224 app .router .add_route ("GET" , "/" , handler )
171225
172226 async def run_client_benchmark () -> None :
173- client = await aiohttp_client (app )
227+ client = await aiohttp_client_sync (app , server_kwargs = conn_type . s_kwargs )
174228 for _ in range (message_count ):
175- resp = await client .get ("/" )
229+ resp = await client .get ("/" , ** conn_type . c_kwargs )
176230 await resp .read ()
177231 await client .close ()
178232
@@ -212,8 +266,9 @@ def _run() -> None:
212266
213267def test_one_hundred_get_requests_with_1mb_chunked_payload (
214268 event_loop : asyncio .AbstractEventLoop ,
215- aiohttp_client : AiohttpClient ,
269+ aiohttp_client_sync : AiohttpClient ,
216270 benchmark : BenchmarkFixture ,
271+ conn_type : ConnectionType ,
217272) -> None :
218273 """Benchmark 100 GET requests with a 1 MiB chunked payload using read."""
219274 message_count = 100
@@ -228,9 +283,9 @@ async def handler(request: web.Request) -> web.Response:
228283 app .router .add_route ("GET" , "/" , handler )
229284
230285 async def run_client_benchmark () -> None :
231- client = await aiohttp_client (app )
286+ client = await aiohttp_client_sync (app , server_kwargs = conn_type . s_kwargs )
232287 for _ in range (message_count ):
233- resp = await client .get ("/" )
288+ resp = await client .get ("/" , ** conn_type . c_kwargs )
234289 await resp .read ()
235290 await client .close ()
236291
0 commit comments