mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-24 18:26:51 +03:00
Rate events over at least one second (#24455)
* Rate events over at least one second EventsPerSecond.eps() divided the event count by the time since start(), which can be a few milliseconds right after a restart. Frames buffered during an ffmpeg restart then report as 100+ fps, and the same happens to the detector fps. Use a window of at least one second. * Keep sub-second windows consistent Floor the divisor at the window length when the window is shorter than a second, so a caller with a sub-second window still gets its true rate.
This commit is contained in:
@@ -36,6 +36,31 @@ class TestEventsPerSecond(unittest.TestCase):
|
||||
clock[0] += 100.0
|
||||
self.assertEqual(eps.eps(), 0.0)
|
||||
|
||||
def test_burst_after_start_is_not_divided_by_a_tiny_window(self) -> None:
|
||||
eps = EventsPerSecond(last_n_seconds=10)
|
||||
clock = [1000.0]
|
||||
with patch("frigate.util.builtin.time.monotonic", side_effect=lambda: clock[0]):
|
||||
eps.start()
|
||||
# eleven buffered frames arrive within 100 ms of starting
|
||||
for _ in range(11):
|
||||
clock[0] += 0.01
|
||||
eps.update()
|
||||
# 11 events over less than a second is at most 11 per second
|
||||
self.assertLessEqual(eps.eps(), 11.0)
|
||||
|
||||
def test_subsecond_window_keeps_its_rate(self) -> None:
|
||||
eps = EventsPerSecond(last_n_seconds=0.5)
|
||||
clock = [1000.0]
|
||||
with patch("frigate.util.builtin.time.monotonic", side_effect=lambda: clock[0]):
|
||||
eps.start()
|
||||
# twenty events per second for two seconds
|
||||
for _ in range(40):
|
||||
clock[0] += 0.05
|
||||
eps.update()
|
||||
# read between events, so none sits exactly on the window edge
|
||||
clock[0] += 0.01
|
||||
self.assertAlmostEqual(eps.eps(), 20.0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -56,10 +56,13 @@ class EventsPerSecond:
|
||||
self._start = now
|
||||
# compute the (approximate) events in the last n seconds
|
||||
self.expire_timestamps(now)
|
||||
seconds = min(now - self._start, self._last_n_seconds)
|
||||
# avoid divide by zero
|
||||
if seconds == 0:
|
||||
seconds = 1
|
||||
# rate over at least one second (or the whole window, if shorter),
|
||||
# so a burst of events right after start() is not divided by a
|
||||
# tiny window
|
||||
seconds = max(
|
||||
min(now - self._start, self._last_n_seconds),
|
||||
min(1.0, self._last_n_seconds),
|
||||
)
|
||||
return len(self._timestamps) / seconds
|
||||
|
||||
# remove aged out timestamps
|
||||
|
||||
Reference in New Issue
Block a user