Skip to content

Commit f96182a

Browse files
[PR #8662/be23d16f backport][3.10] Improve performance of keepalive rescheduling (#8670)
Co-authored-by: J. Nick Koston <nick@koston.org>
1 parent dbcdb16 commit f96182a

File tree

2 files changed

+18
-18
lines changed

2 files changed

+18
-18
lines changed

CHANGES/8662.misc.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Improved performance of HTTP keep-alive checks -- by :user:`bdraco`.
2+
3+
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.

aiohttp/web_protocol.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,14 @@ class RequestHandler(BaseProtocol):
134134
135135
"""
136136

137-
KEEPALIVE_RESCHEDULE_DELAY = 1
138-
139137
__slots__ = (
140138
"_request_count",
141139
"_keepalive",
142140
"_manager",
143141
"_request_handler",
144142
"_request_factory",
145143
"_tcp_keepalive",
146-
"_keepalive_time",
144+
"_next_keepalive_close_time",
147145
"_keepalive_handle",
148146
"_keepalive_timeout",
149147
"_lingering_time",
@@ -197,7 +195,7 @@ def __init__(
197195

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

431429
def _process_keepalive(self) -> None:
430+
self._keepalive_handle = None
432431
if self._force_close or not self._keepalive:
433432
return
434433

435-
next = self._keepalive_time + self._keepalive_timeout
434+
loop = self._loop
435+
now = loop.time()
436+
close_time = self._next_keepalive_close_time
437+
if now <= close_time:
438+
# Keep alive close check fired too early, reschedule
439+
self._keepalive_handle = loop.call_at(close_time, self._process_keepalive)
440+
return
436441

437442
# handler in idle state
438443
if self._waiter:
439-
if self._loop.time() > next:
440-
self.force_close()
441-
return
442-
443-
# not all request handlers are done,
444-
# reschedule itself to next second
445-
self._keepalive_handle = self._loop.call_later(
446-
self.KEEPALIVE_RESCHEDULE_DELAY,
447-
self._process_keepalive,
448-
)
444+
self.force_close()
449445

450446
async def _handle_request(
451447
self,
@@ -596,11 +592,12 @@ async def start(self) -> None:
596592
if self._keepalive and not self._close:
597593
# start keep-alive timer
598594
if keepalive_timeout is not None:
599-
now = self._loop.time()
600-
self._keepalive_time = now
595+
now = loop.time()
596+
close_time = now + keepalive_timeout
597+
self._next_keepalive_close_time = close_time
601598
if self._keepalive_handle is None:
602599
self._keepalive_handle = loop.call_at(
603-
now + keepalive_timeout, self._process_keepalive
600+
close_time, self._process_keepalive
604601
)
605602
else:
606603
break

0 commit comments

Comments
 (0)