Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

common: add MovingAverage class for real-time windowed average calculation #34569

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

deanlee
Copy link
Contributor

@deanlee deanlee commented Feb 11, 2025

This PR replaces the previous deque-based moving average calculation with a new MovingAverage class using a fixed-size circular buffer. This improves performance by reducing memory overhead and making updates more efficient.

Key Changes:

  1. Replaced Deque with Circular Buffer: The deque used to store recent values has been replaced by a circular buffer, eliminating the need for append and pop operations.
  2. Constant Time Updates: Adding new values and updating the average now happens in constant time, regardless of the window size, by maintaining a running sum.
  3. Lower Memory Overhead: By using a fixed-size buffer, we reduce the overhead of dynamic memory allocation and deallocation associated with the deque.

This PR also enhances the Ratekeeper.lagging check, which is invoked multiple times in selfdrived, by eliminating redundant sum calculations,

@deanlee deanlee marked this pull request as ready for review February 11, 2025 18:20
common/moving_average.py Outdated Show resolved Hide resolved
self._last_monitor_time = -1.
self._next_frame_time = -1.

self.avg_dt = MovingAverage(100)
self.avg_dt.add_value(self._interval)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to add a value every time?

Copy link
Contributor Author

@deanlee deanlee Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an initial value in __init__ because ratekeeper calls lagging() before it updates with monitor_time(). This ensures the first call to lagging() returns a valid average, avoiding uninitialized values, similar to how self._dts = deque([self._interval], maxlen=100) works by starting with an initial value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants