Source code for neural_data_simulator.core.timing

"""Implement an accurate timer class that works across platforms."""

import time


[docs]class Timer: """A simple timer class. It has a custom implementation for the python's sleep method by adding a cpu bound routine to wait for the last `n` ms before the next loop execution. """
[docs] def __init__(self, period: float, max_cpu_buffer: float = 0.005): """Initialize timer class. Args: period: Expected time between returns from the wait function (in seconds). max_cpu_buffer: Maximum time to stay in cpu bound loop (i.e. a while loop that does nothing) waiting for correct time to return from a `wait` call (in seconds). Defaults to 0.005. """ self.period_ns = period * 1e9 self.max_cpu_buffer_ns = max_cpu_buffer * 1e9
[docs] def start(self) -> None: """Start the timer.""" self._start_time_ns = time.perf_counter_ns() self._next_loop_ns = self._start_time_ns + self.period_ns self.jitter_ns = 0.0
[docs] def wait(self) -> None: """Wait until the end of the next timer loop. It uses very small sleep intervals to avoid jitters caused by the :meth:`time.sleep` function. """ previous_loop = self._next_loop_ns self._sleep() self._next_loop_ns += self.period_ns self.jitter_ns = -(previous_loop - time.perf_counter_ns())
[docs] def total_elapsed_time(self) -> float: """Get total time since the `start` function call. Returns: Elapsed time (in seconds). """ return (time.perf_counter_ns() - self._start_time_ns) / 1e9
def _sleep(self) -> None: """CPU-bound alternative for the time.sleep method. It uses nanosecond precision and it is more accurate for small intervals above 0ms. It uses max_cpu_buffer_ns to compensate the python's time.sleep jitter. """ sleep_ns = max( (self._next_loop_ns - self.max_cpu_buffer_ns) - time.perf_counter_ns(), 0 ) time.sleep(sleep_ns / 1e9) while time.perf_counter_ns() < self._next_loop_ns: pass
[docs]def get_timer(loop_time: float = 0.02, max_cpu_buffer: float = 0.005) -> Timer: """Get timer object. Args: loop_time: expected time between returns from the wait function (in seconds). max_cpu_buffer: Maximum time to stay in cpu bound loop (i.e. a while loop that does nothing) waiting for correct time to return from a `wait` call (in seconds). Defaults to 0.005. Returns: An instance of the :class:`neural_data_simulator.timing.Timer` class based on input parameters. """ return Timer(loop_time, max_cpu_buffer)