Timers¶
Provides the PrecisionTimer class, Timeout guard, and support functions for timer usage and benchmarking.
- class ataraxis_time.timers.PrecisionTimer(precision=TimerPrecisions.MICROSECOND)¶
Bases:
objectProvides high-precision interval-timing and delay functionality.
This class functions as an interface wrapper for a C++ class that uses the ‘chrono’ library to interface with the highest available precision clock of the host system.
Notes
The precision of all class methods depends on the precision and frequency of the system’s CPU. It is highly advised to benchmark the class before deploying it in time-critical projects to characterize the overhead associated with using different timer methods.
- Parameters:
precision (
str|TimerPrecisions, default:<TimerPrecisions.MICROSECOND: 'us'>) – The desired precision of the timer. Use one of the supported values defined in the TimerPrecisions enumeration. Currently, accepted precision values are ‘ns’ (nanoseconds), ‘us’ (microseconds), ‘ms’ (milliseconds), and ‘s’ (seconds).
- _timer¶
The nanobind-generated C-extension timer class.
- _laps¶
A list of recorded lap times.
- Raises:
ValueError – If the input precision is not one of the accepted options.
- delay(delay, *, allow_sleep=False, block=False)¶
Delays program execution for the requested period of time.
- Parameters:
delay (
int) – The integer period of time to wait for. The method assumes the delay is given in the same precision units as used by the instance.allow_sleep (
bool, default:False) – A boolean flag that allows releasing the CPU while suspending execution for durations above 1 millisecond.block (
bool, default:False) – Determines whether to hold (if True) or release (if False) the Global Interpreter Lock (GIL) during the delay. Releasing the GIL allows other Python threads to run in parallel with the delay.
- Return type:
None
- property elapsed: int¶
Returns the time elapsed since class instantiation or the last reset() method call, whichever happened last.
- format_elapsed(*, max_fields=2)¶
Returns the current elapsed time as a human-readable string.
Converts the elapsed time to seconds internally, then breaks it into descending unit components (d, h, m, s, ms, us, ns). Auto-selects the largest non-zero unit as the starting point and includes up to max_fields unit segments.
- Parameters:
max_fields (
int, default:2) – The maximum number of unit segments to include in the output. Defaults to 2, e.g. “2 h 30 m” instead of “2 h 30 m 15 s 200 ms”.- Return type:
str- Returns:
A human-readable string representation of the elapsed time, e.g. “2 h 30 m”, “1.5 ms”, “500 ns”.
- lap()¶
Records the current elapsed time as a lap, resets the timer, and returns the lap duration.
- Return type:
int- Returns:
The elapsed time captured as the lap duration, in the timer’s current precision units.
- property laps: tuple[int, ...]¶
Returns all recorded lap times as a tuple.
- poll(interval, *, allow_sleep=True, block=False)¶
Infinite generator that yields an iteration count after each delay cycle.
Each iteration calls self.delay() with the specified interval and parameters. The caller should break out of the loop when done.
- Parameters:
interval (
int) – The delay interval in the timer’s current precision units.allow_sleep (
bool, default:True) – A boolean flag that allows releasing the CPU while suspending execution for durations above 1 millisecond.block (
bool, default:False) – Determines whether to hold or release the GIL during the delay.
- Yields:
The iteration count (starting from 1) after each delay cycle.
- Return type:
Generator[int,None,None]
- property precision: str¶
Returns the units currently used by the instance as a string (‘ns’, ‘us’, ‘ms’, or ‘s’).
- reset()¶
Resets the timer and clears all recorded laps.
- Return type:
None
- set_precision(precision)¶
Changes the precision used by the timer to the input option.
- Parameters:
precision (
str|TimerPrecisions) – The desired precision of the timer. Use one of the supported values defined in the TimerPrecisions enumeration. Currently, accepted precision values are ‘ns’ (nanoseconds), ‘us’ (microseconds), ‘ms’ (milliseconds), and ‘s’ (seconds).- Raises:
ValueError – If the input precision is not one of the accepted options.
- Return type:
None
- class ataraxis_time.timers.Timeout(duration, precision=TimerPrecisions.MICROSECOND)¶
Bases:
objectProvides a timeout guard built on PrecisionTimer.
This class wraps a PrecisionTimer instance and provides a convenient API for checking whether a specified duration has elapsed. It supports activity-based reset (kick) and full reset with optional duration changes.
- Parameters:
duration (
int) – The timeout duration in the timer’s precision units. Must be greater than 0.precision (
str|TimerPrecisions, default:<TimerPrecisions.MICROSECOND: 'us'>) – The precision to use for timeout tracking. Use one of the supported values defined in the TimerPrecisions enumeration.
- _timer¶
The internal PrecisionTimer instance.
- _duration¶
The timeout duration.
- Raises:
ValueError – If the duration is not greater than 0, or if the precision is not a valid option.
- property elapsed: int¶
Returns elapsed time since creation or last reset.
- property expired: bool¶
Returns True if the timeout duration has elapsed.
- kick()¶
Resets the timeout timer (for activity-based timeouts).
This resets the internal timer without changing the duration, effectively restarting the timeout countdown.
- Return type:
None
- property remaining: int¶
Returns the remaining time before expiry (0 if expired).
- reset(duration=None)¶
Resets the timeout, optionally with a new duration.
- Parameters:
duration (
int|None, default:None) – An optional new duration for the timeout. If None, the current duration is preserved. Must be greater than 0 if provided.- Raises:
ValueError – If the provided duration is not greater than 0.
- Return type:
None
- class ataraxis_time.timers.TimerPrecisions(*values)¶
Bases:
StrEnumDefines the timer precision modes supported by PrecisionTimer instances.
Use this enumeration when initializing or reconfiguring the precision used by a PrecisionTimer instance.
- MICROSECOND = 'us'¶
Microsecond precision.
- MILLISECOND = 'ms'¶
Millisecond precision.
- NANOSECOND = 'ns'¶
Nanosecond precision.
- SECOND = 's'¶
Second precision.
Timer Benchmark¶
axt-benchmark¶
Benchmarks the PrecisionTimer class performance on the local host-system. Use this command to determine the actual precision of the timer for the local Operating System and CPU clock combination.
Usage
axt-benchmark [OPTIONS]
Options
- -ic, --interval-cycles <interval_cycles>¶
The number of times to repeat the interval benchmark for each of the tested timer precisions.
- Default:
60
- -id, --interval-delay <interval_delay>¶
The interval duration, in seconds, to use during the interval benchmark for each of the tested timer precisions.
- Default:
1
- -dc, --delay-cycles <delay_cycles>¶
The number of times to repeat the delay benchmark for each of the tested timer precisions. Expects a space-separated sequence in the order of: ns, us, ms, s.
- Default:
1000, 1000, 1000, 60
- -dd, --delay-durations <delay_durations>¶
The delay duration, in precision-units, to use during the delay benchmark for the tested precisions. Expects a space-separated sequence in the order of: ns, us, ms, s.
- Default:
500, 5, 2, 1
Utilities¶
Provides general-purpose utility functions for working with date and time data.
- class ataraxis_time.utilities.TimeUnits(*values)¶
Bases:
StrEnumDefines the time units supported by the convert_time() function.
Use this enumeration to specify the source and destination time units when calling the conversion function.
- DAY = 'd'¶
Day time unit.
- HOUR = 'h'¶
Hour time unit.
- MICROSECOND = 'us'¶
Microsecond time unit.
- MILLISECOND = 'ms'¶
Millisecond time unit.
- MINUTE = 'm'¶
Minute time unit.
- NANOSECOND = 'ns'¶
Nanosecond time unit.
- SECOND = 's'¶
Second time unit.
- class ataraxis_time.utilities.TimestampFormats(*values)¶
Bases:
StrEnumDefines the timestamp formats supported by the get_timestamp() and the convert_timestamp() functions.
Use this enumeration when generating or converting timestamps.
- BYTES = 'byte'¶
A NumPy byte array. The timestamp is stored as a 64-bit unsigned integer serialized using little endian scheme that represents the number of microseconds elapsed since the UTC epoch onset.
- INTEGER = 'int'¶
The integer that represents the number of microseconds elapsed since the UTC epoch onset.
- STRING = 'str'¶
A delimited date-and-time string. The timestamp is stored in the ‘YYYY-MM-DD-HH-MM-SS-ssssss’ format and uses UTC timezone.
- class ataraxis_time.utilities.TimestampPrecisions(*values)¶
Bases:
StrEnumDefines the precision levels supported by timestamp functions.
Use this enumeration to control how much detail is included in generated or converted timestamps.
- DAY = 'day'¶
Day precision (YYYY-MM-DD).
- HOUR = 'hour'¶
Hour precision (YYYY-MM-DD-HH).
- MICROSECOND = 'microsecond'¶
Microsecond precision (YYYY-MM-DD-HH-MM-SS-ssssss). This is the default and preserves full detail.
- MINUTE = 'minute'¶
Minute precision (YYYY-MM-DD-HH-MM).
- MONTH = 'month'¶
Month precision (YYYY-MM).
- SECOND = 'second'¶
Second precision (YYYY-MM-DD-HH-MM-SS).
- YEAR = 'year'¶
Year precision (YYYY).
- ataraxis_time.utilities.convert_time(time, from_units, to_units, *, as_float=False)¶
Converts the input time value from the original units to the requested units.
Notes
By default, this function returns the converted time value as a NumPy 64-bit floating scalar.
The conversion uses 3 decimal places rounding.
- Parameters:
time (
float|integer[Any] |floating[Any]) – The time-value to convert.from_units (
str|TimeUnits) – The units used by the input data. Use one of the valid options defined in the TimeUnits enumeration: ‘ns’ (nanoseconds), ‘us’ (microseconds), ‘ms’ (milliseconds), ‘s’ (seconds), ‘m’ (minutes), ‘h’ (hours), ‘d’ (days).to_units (
str|TimeUnits) – The units to convert the input data to. Uses the same options as the ‘from_units’ argument.as_float (
bool, default:False) – Determines whether to return the converted time as a Python floating object (if True) or a NumPy 64-bit floating scalar type (if False).
- Return type:
float|float64- Returns:
The converted time-value given in the requested time-units. Depending on the ‘as_float’ argument, the value is returned either as a Python float or a NumPy 64-bit floating scalar.
- Raises:
ValueError – If ‘from_units’ or ‘to_units’ argument is not set to a valid time-option.
- ataraxis_time.utilities.convert_timestamp(timestamp, time_separator='-', output_format=TimestampFormats.STRING, precision=TimestampPrecisions.MICROSECOND)¶
Converts a timestamp generated by the get_timestamp() function into a different format.
Notes
This method is primarily designed to decode byte-serialized timestamps produced by the get_timestamp() function into other formats. String inputs may have 1 to 7 delimited parts; missing fields are filled with defaults (month=1, day=1, hour=0, minute=0, second=0, microsecond=0).
- Parameters:
timestamp (
str|int|ndarray[tuple[Any,...],dtype[uint8]]) – The timestamp value to convert.time_separator (
str, default:'-') – The separator to use for delimiting the date-and-time string. This is used when parsing input date-and-time strings and when converting timestamps to the string format.output_format (
str|TimestampFormats, default:<TimestampFormats.STRING: 'str'>) – The format in which to return the timestamp. Use one of the valid options defined in the TimestampFormats enumeration: “str”, “byte”, or “int”.precision (
str|TimestampPrecisions, default:<TimestampPrecisions.MICROSECOND: 'microsecond'>) – The precision level for the output timestamp. Use one of the valid options defined in the TimestampPrecisions enumeration. For STRING format, this controls how many date/time components are included. For INTEGER and BYTES formats, sub-precision fields are zeroed out.
- Return type:
str|int|ndarray[tuple[Any,...],dtype[uint8]]- Returns:
The timestamp converted to the requested format.
- Raises:
TypeError – If the ‘time_separator’ argument is not a string, or if the ‘timestamp’ argument is not of a valid type.
ValueError – If the ‘output_format’ argument is not set to a valid format option, or if the ‘precision’ argument is not a valid TimestampPrecisions value.
- ataraxis_time.utilities.from_timedelta(timedelta_value, to_units, *, as_float=False)¶
Converts a datetime.timedelta to a numeric value in the requested units.
- Parameters:
timedelta_value (
timedelta) – The timedelta to convert.to_units (
str|TimeUnits) – The units for the output value. Use one of the valid options defined in the TimeUnits enumeration.as_float (
bool, default:False) – Determines whether to return the result as a Python float (if True) or a NumPy 64-bit floating scalar (if False).
- Return type:
float|float64- Returns:
The numeric value of the timedelta in the requested units.
- Raises:
ValueError – If to_units is not a valid time unit.
- ataraxis_time.utilities.get_timestamp(output_format=TimestampFormats.STRING, time_separator='-', precision=TimestampPrecisions.MICROSECOND)¶
Gets the current Coordinated Universal Time (UTC) timestamp (date and time) and returns it using the requested output format.
Notes
The bytes’-converted timestamp is encoded using the little-endian format.
- Parameters:
output_format (
str|TimestampFormats, default:<TimestampFormats.STRING: 'str'>) – The format in which to return the timestamp. Use one of the valid options defined in the TimestampFormats enumeration: “str”, “byte”, or “int”.time_separator (
str, default:'-') – The separator to use for delimiting the date-and-time string. This is only used if the ‘output_format’ argument is set to “str”.precision (
str|TimestampPrecisions, default:<TimestampPrecisions.MICROSECOND: 'microsecond'>) – The precision level for the output timestamp. Use one of the valid options defined in the TimestampPrecisions enumeration. For STRING format, this controls how many date/time components are included. For INTEGER and BYTES formats, sub-precision fields are zeroed out.
- Return type:
str|int|ndarray[tuple[Any,...],dtype[uint8]]- Returns:
The current UTC timestamp converted to the requested output format.
- Raises:
TypeError – If the ‘time_separator’ argument is not a string.
ValueError – If the ‘output_format’ argument is not set to a valid format option, or if the ‘precision’ argument is not a valid TimestampPrecisions value.
- ataraxis_time.utilities.interval_to_rate(interval, from_units=TimeUnits.MICROSECOND, *, as_float=False)¶
Converts a time interval to a frequency in Hz.
- Parameters:
interval (
float|integer[Any] |floating[Any]) – The time interval to convert. Must be greater than 0.from_units (
str|TimeUnits, default:<TimeUnits.MICROSECOND: 'us'>) – The time units of the input interval. Use one of the valid options defined in the TimeUnits enumeration.as_float (
bool, default:False) – Determines whether to return the result as a Python float (if True) or a NumPy 64-bit floating scalar (if False).
- Return type:
float|float64- Returns:
The frequency in Hz corresponding to the given time interval.
- Raises:
ValueError – If the interval is not greater than 0, or if from_units is not a valid time unit.
- ataraxis_time.utilities.parse_timestamp(date_string, format_string, *, output_format=TimestampFormats.INTEGER, time_separator='-', precision=TimestampPrecisions.MICROSECOND)¶
Parses an arbitrary datetime string and returns it as a timestamp in the requested format.
Notes
The input datetime string is parsed using datetime.strptime() with the provided format string. The parsed datetime is assumed to be in UTC timezone. The output respects the same format and precision options as get_timestamp() and convert_timestamp().
- Parameters:
date_string (
str) – The datetime string to parse.format_string (
str) – The strptime-compatible format string used to parse the date_string.output_format (
str|TimestampFormats, default:<TimestampFormats.INTEGER: 'int'>) – The format in which to return the timestamp. Use one of the valid options defined in the TimestampFormats enumeration: “str”, “byte”, or “int”.time_separator (
str, default:'-') – The separator to use for delimiting the date-and-time string. This is only used if the ‘output_format’ argument is set to “str”.precision (
str|TimestampPrecisions, default:<TimestampPrecisions.MICROSECOND: 'microsecond'>) – The precision level for the output timestamp. Use one of the valid options defined in the TimestampPrecisions enumeration.
- Return type:
str|int|ndarray[tuple[Any,...],dtype[uint8]]- Returns:
The parsed timestamp in the requested output format.
- Raises:
ValueError – If the date_string cannot be parsed with the provided format_string, if the output_format is invalid, or if the precision is invalid.
- ataraxis_time.utilities.rate_to_interval(rate, to_units=TimeUnits.MICROSECOND, *, as_float=False)¶
Converts a frequency in Hz to a time interval in the requested units.
- Parameters:
rate (
float|integer[Any] |floating[Any]) – The frequency in Hz to convert. Must be greater than 0.to_units (
str|TimeUnits, default:<TimeUnits.MICROSECOND: 'us'>) – The time units for the output interval. Use one of the valid options defined in the TimeUnits enumeration.as_float (
bool, default:False) – Determines whether to return the result as a Python float (if True) or a NumPy 64-bit floating scalar (if False).
- Return type:
float|float64- Returns:
The time interval corresponding to the given frequency, in the requested units.
- Raises:
ValueError – If the rate is not greater than 0, or if to_units is not a valid time unit.
- ataraxis_time.utilities.to_timedelta(time, from_units)¶
Converts a time value in the given units to a datetime.timedelta.
- Parameters:
time (
float|integer[Any] |floating[Any]) – The time value to convert.from_units (
str|TimeUnits) – The units of the input time value. Use one of the valid options defined in the TimeUnits enumeration.
- Return type:
timedelta- Returns:
A datetime.timedelta representing the given time value.
- Raises:
ValueError – If from_units is not a valid time unit.
C++ Timer Extension¶
Defines and implements the CPrecisionTimer class as a nanobind-bound C++ extension module.
Uses the fastest system clock available through the ‘chrono’ library, which allows the timer to resolve sub-microsecond intervals on sufficiently fast CPUs. This module works on Windows, macOS, and Linux.
Note
This module is bound to Python using nanobind and is designed to be further wrapped with a pure-Python PrecisionTimer class. The binding code is stored at the end of this file.
Functions
-
NB_MODULE(precision_timer_ext, m)¶
Binds the CPrecisionTimer class to the Python API via nanobind.
The module is available as ‘precision_timer_ext’ and must be bound to a Python package via CMake configuration. Each method exposed to the Python API uses the name given as the first argument to each ‘def’ call.
-
class CPrecisionTimer¶
Provides methods for sub-microsecond-precise interval timing and blocking / non-blocking code execution delays.
Note
The performance of this class scales with the OS and the state of the host system. The ‘chrono’ library provides a high_resolution_clock, which is automatically set to the highest resolution clock of the host OS. However, all method calls have a certain overhead associated with them and the busier the OS is, the longer the overhead.
Public Functions
-
inline explicit CPrecisionTimer(const std::string &precision = "us")¶
Instantiates the CPrecisionTimer class using the requested precision.
- Parameters:
precision – The precision of the timer. This controls the units used by the timer for all inputs and outputs. Supported values are: ‘ns’ (nanoseconds), ‘us’ (microseconds), ‘ms’ (milliseconds), and ‘s’ (seconds).
-
inline void Reset()¶
Resets the timer.
-
inline int64_t Elapsed() const¶
Returns the time elapsed since the last reset() method call or class instantiation.
- Returns:
int64_t The elapsed time, using the current class precision units.
-
inline void Delay(const int64_t duration, const bool allow_sleep = false, const bool block = false) const¶
Blocks (delays) in-place for the specified number of time-units (depends on used precision).
This method is used to execute arbitrary delays while maintaining or releasing the Global Interpreter Lock (GIL). By default, this method uses a busy-wait approach where the thread constantly checks elapsed time until the exit condition is encountered and releases the GIL while waiting.
Warning
If sleeping is allowed, there is an overhead of up to 1 millisecond due to scheduling on the Windows OS.
- Parameters:
duration – The time to block for. Uses the same units as the instance’s precision parameter.
allow_sleep – Determines whether the method should use sleep for delay durations above 1 millisecond. Sleep may be beneficial in some cases as it reduces the CPU load at the expense of an additional overhead compared to the default busy-wait delay approach.
block – Determines whether the method should release the GIL, allowing concurrent execution of other Python threads. If false, the method releases the GIL. If true, the method maintains the GIL, preventing other Python threads from running.
-
inline void SetPrecision(const std::string &precision)¶
Changes the timer precision used by the instance to the requested units.
This method can be used to dynamically change the precision used by a class instance during runtime.
- Parameters:
precision – The new precision to use. Supported values are: ‘ns’ (nanoseconds), ‘us’ (microseconds), ‘ms’ (milliseconds), and ‘s’ (seconds).
-
inline std::string GetPrecision() const¶
Returns the current precision (time-units) of the timer.
- Returns:
std::string The current precision of the timer (‘ns’, ‘us’, ‘ms’, or ‘s’).
-
~CPrecisionTimer() = default¶
Destroys the CPrecisionTimer class.
Private Functions
-
inline int64_t ConvertToPrecision(const int64_t nanoseconds) const¶
Converts the input value from nanoseconds to the chosen precision units.
This method is currently used by the Elapsed() method to convert elapsed time from nanoseconds (used by the class) to the desired precision (requested by the user). However, it is a general converter that may be used by other methods in the future.
- Parameters:
nanoseconds – The value in nanoseconds to be converted to the desired precision.
- Returns:
int64_t The converted time-value, rounded to the whole number.
Private Members
-
high_resolution_clock::time_point _start_time¶
Stores the reference value used to calculate elapsed time.
-
std::string _precision¶
Stores the string-option that describes the units used for inputs and outputs.
-
nanoseconds _precision_duration = microseconds(1)¶
Stores the conversion factor that is assigned based on the chosen _precision option. It is used to convert the input duration values (for delay methods) to nanoseconds and the output duration values from nanoseconds to the chosen precision units.
-
inline explicit CPrecisionTimer(const std::string &precision = "us")¶
-
namespace literals¶
Provides the ability to work with Python literal string-options.
-
namespace chrono¶
Provides the binding for various clock-related operations.