Skip to content

Commit

Permalink
[PR #8662/be23d16f backport][3.10] Improve performance of keepalive r…
Browse files Browse the repository at this point in the history
…escheduling (#8670)

Co-authored-by: J. Nick Koston <[email protected]>
  • Loading branch information
patchback[bot] and bdraco authored Aug 9, 2024
1 parent dbcdb16 commit f96182a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 18 deletions.
3 changes: 3 additions & 0 deletions CHANGES/8662.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Improved performance of HTTP keep-alive checks -- by :user:`bdraco`.

Previously, when processing a request for a keep-alive connection, the keep-alive check would happen every second; the check is now rescheduled if it fires too early instead.
33 changes: 15 additions & 18 deletions aiohttp/web_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,14 @@ class RequestHandler(BaseProtocol):
"""

KEEPALIVE_RESCHEDULE_DELAY = 1

__slots__ = (
"_request_count",
"_keepalive",
"_manager",
"_request_handler",
"_request_factory",
"_tcp_keepalive",
"_keepalive_time",
"_next_keepalive_close_time",
"_keepalive_handle",
"_keepalive_timeout",
"_lingering_time",
Expand Down Expand Up @@ -197,7 +195,7 @@ def __init__(

self._tcp_keepalive = tcp_keepalive
# placeholder to be replaced on keepalive timeout setup
self._keepalive_time = 0.0
self._next_keepalive_close_time = 0.0
self._keepalive_handle: Optional[asyncio.Handle] = None
self._keepalive_timeout = keepalive_timeout
self._lingering_time = float(lingering_time)
Expand Down Expand Up @@ -429,23 +427,21 @@ def log_exception(self, *args: Any, **kw: Any) -> None:
self.logger.exception(*args, **kw)

def _process_keepalive(self) -> None:
self._keepalive_handle = None
if self._force_close or not self._keepalive:
return

next = self._keepalive_time + self._keepalive_timeout
loop = self._loop
now = loop.time()
close_time = self._next_keepalive_close_time
if now <= close_time:
# Keep alive close check fired too early, reschedule
self._keepalive_handle = loop.call_at(close_time, self._process_keepalive)
return

# handler in idle state
if self._waiter:
if self._loop.time() > next:
self.force_close()
return

# not all request handlers are done,
# reschedule itself to next second
self._keepalive_handle = self._loop.call_later(
self.KEEPALIVE_RESCHEDULE_DELAY,
self._process_keepalive,
)
self.force_close()

async def _handle_request(
self,
Expand Down Expand Up @@ -596,11 +592,12 @@ async def start(self) -> None:
if self._keepalive and not self._close:
# start keep-alive timer
if keepalive_timeout is not None:
now = self._loop.time()
self._keepalive_time = now
now = loop.time()
close_time = now + keepalive_timeout
self._next_keepalive_close_time = close_time
if self._keepalive_handle is None:
self._keepalive_handle = loop.call_at(
now + keepalive_timeout, self._process_keepalive
close_time, self._process_keepalive
)
else:
break
Expand Down

0 comments on commit f96182a

Please sign in to comment.