From a892e916b914ce3ad4e72ad09bb6cf11ec6e7bc4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Aug 2024 17:38:03 -0500 Subject: [PATCH 1/3] Improve performance of starting request handlers with Python 3.12+ #3406 wrapped _handle_request in a task to copy the contextvars which delays the start of the request by one iteration of the event loop. In https://github.com/aio-libs/aiohttp/discussions/8170#discussioncomment-8802876 we did not have a way to improve with without removing the task, however since Python 3.12+ has eager start for tasks, we can now avoid the delay. --- aiohttp/web_protocol.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index 4d50465b2ef..3accf4b1bcc 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -1,6 +1,7 @@ import asyncio import asyncio.streams import dataclasses +import sys import traceback from collections import deque from contextlib import suppress @@ -543,9 +544,11 @@ async def start(self) -> None: request = self._request_factory(message, payload, self, writer, handler) try: # a new task is used for copy context vars (#3406) - task = self._loop.create_task( - self._handle_request(request, start, request_handler) - ) + coro = self._handle_request(request, start, request_handler) + if sys.version_info >= (3, 12): + task = asyncio.create_task(coro, eager_start=True) + else: + task = self._loop.create_task(coro) try: resp, reset = await task except (asyncio.CancelledError, ConnectionError): From 3482ab37b2b17dddc1f3458d9fa8c5c199260a81 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Aug 2024 17:39:35 -0500 Subject: [PATCH 2/3] Improve performance of starting request handlers with Python 3.12+ #3406 wrapped _handle_request in a task to copy the contextvars which delays the start of the request by one iteration of the event loop. In https://github.com/aio-libs/aiohttp/discussions/8170#discussioncomment-8802876 we did not have a way to improve with without removing the task, however since Python 3.12+ has eager start for tasks, we can now avoid the delay. --- aiohttp/web_protocol.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aiohttp/web_protocol.py b/aiohttp/web_protocol.py index 3accf4b1bcc..79708a58cfb 100644 --- a/aiohttp/web_protocol.py +++ b/aiohttp/web_protocol.py @@ -546,9 +546,9 @@ async def start(self) -> None: # a new task is used for copy context vars (#3406) coro = self._handle_request(request, start, request_handler) if sys.version_info >= (3, 12): - task = asyncio.create_task(coro, eager_start=True) + task = asyncio.Task(coro, loop=loop, eager_start=True) else: - task = self._loop.create_task(coro) + task = loop.create_task(coro) try: resp, reset = await task except (asyncio.CancelledError, ConnectionError): From a4a0dd3199ee1a7bbf1818dbe09488aa2cfa5840 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Aug 2024 18:12:23 -0500 Subject: [PATCH 3/3] changelog --- CHANGES/8661.misc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGES/8661.misc.rst diff --git a/CHANGES/8661.misc.rst b/CHANGES/8661.misc.rst new file mode 100644 index 00000000000..c0a6fdadb37 --- /dev/null +++ b/CHANGES/8661.misc.rst @@ -0,0 +1 @@ +Improved performance of starting request handlers with Python 3.12+ -- by :user:`bdraco`.