Skip to content

Commit de0cc62

Browse files
author
Greg Barnett
committed
bugfix and simplification in TimeService
The main bug was that ceil was called on time returned by loop.time() before being used to schedule the next iteration of the callback that updated the TimeService. The TimeService was then incrementing its stored time by one second. This resulted in the time being updated by one second about every 1.5 seconds, quickly causing it to fall behind. There was code to reset TimeService's internal time every 10 minutes, but that has been removed. Benchmarking has shown that just calling time.time() has no statistically valid performance difference than the code that checked for the need to reset. Even if it were slightly slower, it is only called once per second. Also, the counter that was used to compare to the reset limit was never incremented, so the reset never actually ever happened. I was tempted to remove the properties for accessing time and loop time, as time.time() and loop.time() are not expensive calls. But I didn't want to break the API for anyone using this. The only significant performance gain I was able to find was with strtime. My use case doesn't push aiohttp very hard, so I can't replicate whatever performance issue TimeService was intended to solve.
1 parent ee69c40 commit de0cc62

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

aiohttp/helpers.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -576,11 +576,11 @@ class TimeService:
576576
def __init__(self, loop, *, interval=1.0):
577577
self._loop = loop
578578
self._interval = interval
579+
579580
self._time = time.time()
580-
self._loop_time = loop.time()
581-
self._count = 0
582581
self._strtime = None
583-
self._cb = loop.call_at(self._loop_time + self._interval, self._on_cb)
582+
self._loop_time = ceil(self._loop.time())
583+
self._cb = self._loop.call_soon(self._on_cb)
584584

585585
def close(self):
586586
if self._cb:
@@ -589,18 +589,12 @@ def close(self):
589589
self._cb = None
590590
self._loop = None
591591

592-
def _on_cb(self, reset_count=10*60):
593-
if self._count >= reset_count:
594-
# reset timer every 10 minutes
595-
self._count = 0
596-
self._time = time.time()
597-
else:
598-
self._time += self._interval
599-
592+
def _on_cb(self):
593+
self._time = time.time()
600594
self._strtime = None
601-
self._loop_time = ceil(self._loop.time())
602-
self._cb = self._loop.call_at(
603-
self._loop_time + self._interval, self._on_cb)
595+
_loop_time = self._loop.time()
596+
self._loop_time = ceil(_loop_time)
597+
self._cb = self._loop.call_at(_loop_time + self._interval, self._on_cb)
604598

605599
def _format_date_time(self):
606600
# Weekday and month names for HTTP date/time formatting;

tests/test_helpers.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,15 +411,31 @@ def test_strtime(self, time_service):
411411
# second call should use cached value
412412
assert time_service.strtime() == 'Sun, 30 Oct 2016 03:13:52 GMT'
413413

414-
def test_recalc_time(self, time_service, mocker):
414+
def test_recalc_time(self, time_service):
415415
time = time_service._loop.time()
416416
time_service._time = time
417417
time_service._strtime = 'asd'
418-
time_service._count = 1000000
419418
time_service._on_cb()
420419
assert time_service._strtime is None
421420
assert time_service._time > time
422-
assert time_service._count == 0
421+
assert time_service._loop_time > time
422+
423+
def test_on_cb_calls_on_cb_with_proper_delay(self, time_service):
424+
mock_loop = mock.Mock()
425+
mock_loop.time.side_effect = [1.1, 2.1]
426+
mock_loop.call_at = mock.Mock()
427+
time_service._loop = mock_loop
428+
time_service._time = 0.5
429+
time_service._interval = 1.0
430+
431+
start_time = time_service._time
432+
time_service._on_cb()
433+
mock_loop.call_at.assert_called_with(1.1 + time_service._interval, time_service._on_cb)
434+
assert time_service._loop_time == 2
435+
436+
time_service._on_cb()
437+
mock_loop.call_at.assert_called_with(2.1 + time_service._interval, time_service._on_cb)
438+
assert time_service._loop_time == 3
423439

424440

425441
# ----------------------------------- TimeoutHandle -------------------

0 commit comments

Comments
 (0)