MODULES¶
Timer¶
Utilities to measure time from system and custom clocks/counters.
- Classes:
Todo
- Extend to support additional stats besides time (e.g. psutil).
- Support timing concurrent processes, use time.thread_time() (requires Python 3.7).
-
class
smarttimer.timer.
TimerDict
(tdict={})[source]¶ Map between label identifier and callable object.
Parameters: tdict (dict, TimerDict, optional) – Dictionary for initialization.
Raises: TimerTypeError
– If tdict is not derived from dict.TimerKeyError
– If keys are not strings or does not exists.TimerValueError
– If value is not a callable object.
-
class
smarttimer.timer.
Timer
(label='', **kwargs)[source]¶ Read current time from a clock/counter.
Parameters: - label (str, optional) – Label identifier. Default is empty string.
- seconds (float, optional) – Time measured in fractional seconds. Default is 0.0.
- clock_name (str, optional) – Clock name used to select a time
measurement function. Default is
DEFAULT_CLOCK_NAME
. - timer (dict, TimerDict, optional) –
Timer
for initialization.
A
Timer
allows recording the current time measured by a registered timing function. Time is recorded in fractional seconds and fractional minutes.Timer
supports addition, difference, and logical operators.Timer
uses a simple and extensible API which allows registering new timing functions. A timing function is compliant if it returns a time measured in fractional seconds. The function can contain arbitrary positional and/or keyword arguments or no arguments.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
from smarttimer import Timer # Find the current time function of a Timer t1 = Timer('Timer1') print(Timer.CLOCKS[t1.clock_name]) # or Timer.print_clocks() print(t1.clock_name) # Change current time function t1.clock_name = 'process_time' # Record a time measurement t1.time() print(t1) # Create another Timer compatible with 'Timer1' t2 = Timer('Timer2', clock_name='process_time') t2.print_info() t2.time() print(t2) # Sum Timers t3 = Timer.sum(t1, t2) # or t3 = t1 + t2 print(t3) # Find difference between Timers t4 = Timer.diff(t1, t2) # or t4 = t2 - t1 print(t4) # Compare Timers print(t1 == t2) # False print(t2 > t1) # True print(t4 <= t3) # True
- Available time measurement functions in
CLOCKS
- ‘perf_counter’ -> time.perf_counter()
- ‘process_time’ -> time.process_time()
- ‘clock’ -> time.clock()
- ‘monotonic’ -> time.monotonic()
- ‘time’ -> time.time()
def custom_time_function(*args, **kwargs): # Measure time time_in_some_unit = ... # Convert time to fractional seconds time_seconds = time_in_some_unit ... return time_seconds # Register custom_time_function() as 'custom_time' Timer.register_clock('custom_time', custom_time_function) # or Timer.CLOCKS['custom_time'] = custom_time_function
Note
- New timing functions need to have a compliant interface. If a user wants to register a non-compliant timing function, a compliant wrapper function can be used. The available timing functions are built-ins from the standard time library.
- Only Timers with compatible clocks support arithmetic and logical
operators. Otherwise a
TimerCompatibilityError
exception occurs.
Warning
When registering a new timing function to
CLOCKS
, it is recommended to use a unique clock name to prevent overwriting over an existing one.-
DEFAULT_CLOCK_NAME
¶ str – Default clock name, used when
clock_name
is empty string.Raises: TimerTypeError
– If not a string.
-
CLOCKS
¶ TimerDict
, str -> callable – Map between clock name and time measurement functions.Raises: TimerTypeError
– If not assigned with dictionary.TimerKeyError
– If key is not a string.TimerValueError
– If assigned item is not callable.
-
label
¶ str – Label identifier.
Raises: TimerTypeError
– If not a string.
-
seconds
¶ float – Time measured in fractional seconds (read-only).
Set internally either during initialization or when recording time.
Raises: TimerTypeError
– If not numeric.TimerValueError
– If negative number.
-
minutes
¶ float – Time measured in minutes (read-only).
-
clock_name
¶ str – Clock name used to select a time measurement function.
Indexes the
CLOCKS
map to select a time function. If set to the empty string thenDEFAULT_CLOCK_NAME
is used. An instance is reset when set to a new and incompatible clock name.Raises: TimerTypeError
– If not a string.
-
time
(*args, **kwargs)[source]¶ Invoke time measurement function and record measured time.
Calls timing function currently configured via
clock_name
. This method accepts arbitrary positional and/or keyword arguments to enable support for arbitrary signatures of timing functions.Parameters: - args (tuple, optional) – Positional arguments for time function.
- kwargs (dict, optional) – Keyword arguments for time function.
Returns: Time measured in fractional seconds.
Return type: float
-
get_info
()[source]¶ Return clock information.
For
clock_name
that can be queried with time.get_clock_info, forward the output namespace object. Otherwise create and populate a namespace with the timing function.Returns: Namespace with clock info. Return type: types.SimpleNamespace
-
is_compatible
(other)[source]¶ Return truth of compatibility between a
Timer
pair.For a
clock_name
that can be queried with time.get_clock_info, compatibility requires that all attributes are identical. All other cases require that the timing functions are the same function.Parameters: other (Timer) – Second instance. Returns: True if compatible, else False. Return type: bool
-
classmethod
sum
(timer1, timer2)[source]¶ Compute the time sum of a
Timer
pair.This method wraps the addition operator between
Timer
objects. Thelabel
of the resultingTimer
contains a combination of timer1 and timer2label
. Theclock_name
of the resultingTimer
is set to the clock name of timer1.Parameters: Returns: Instance containing the time sum.
Return type: Raises: TimerCompatibilityError
– If not compatible.
-
classmethod
diff
(timer1, timer2)[source]¶ Compute the absolute time difference of a
Timer
pair.This method wraps the difference operator between
Timer
objects. Thelabel
of the resultingTimer
contains a combination of timer1 and timer2label
. Theclock_name
of the resultingTimer
is set to the clock name of timer1.Parameters: Returns: Instance containing the absolute time difference.
Return type: Raises: TimerCompatibilityError
– If not compatible.
-
classmethod
register_clock
(clock_name, clock_func)[source]¶ Registers a time function to
CLOCKS
map.If a mapping already exists for clock_name, it will be updated with clock_func. For invalid arguments, error handling is expected from
CLOCKS
properties.Parameters: - clock_name (str) – Clock name.
- clock_func (callable) – Reference to a time measurement function.
-
class
smarttimer.timer.
MetaTimerProperty
[source]¶ Metaclass for
Timer
class variables.Requires
TimerDict
.Raises: TimerTypeError
– If set property uses an invalid type.
-
class
smarttimer.timer.
TimerDict
(tdict={})[source] Map between label identifier and callable object.
Parameters: tdict (dict, TimerDict, optional) – Dictionary for initialization.
Raises: TimerTypeError
– If tdict is not derived from dict.TimerKeyError
– If keys are not strings or does not exists.TimerValueError
– If value is not a callable object.
SmartTimer¶
SmartTimer
- Classes:
SmartTimer
-
class
smarttimer.smarttimer.
SmartTimer
(name='smarttimer', **kwargs)[source]¶ Manager of
Timer
measurements for code blocks.- Supports the following schemes of timed blocks:
- Consecutive: tic(), toc(), …, tic(), toc()
- Nested: tic(), tic(), …, toc(), toc()
- Cascade: tic(), toc(), toc(), …
- Nested interleaved: tic(), tic(), toc(), tic(), …, toc(), toc()
- Key-paired: tic(‘outer’), tic(‘inner’), …, toc(‘outer’), toc()
-
labels
¶ Lists of time labels for completed blocks.
Returns: Labels of completed blocks. Return type: list
-
active_labels
¶ Lists of time labels for active blocks.
Returns: Labels of blocks without a matching toc(). Return type: list
-
seconds
¶ List of seconds elapsed for completed blocks.
Returns: Time in seconds. Return type: list
-
minutes
¶ List of minutes elapsed for completed blocks.
Returns: Time in minutes. Return type: list
-
times
¶ Dictionary of times elapsed for completed blocks.
Returns: Keys are labels and values list of time in seconds. Return type: list
-
__getitem__
(*keys)[source]¶ Use dictionary syntax to access time in seconds
The values returned correspond to the time in seconds. Multiple values are returned as a list, generally in the same order as the given keys (except for cases where duplicate labels exist).
Note
- If key is string, then consider it as a label
- If key is integer or slice, then consider it as an index
- Key types can be mixed
Example
timer[4, 2] timer[‘I/O’, ‘Processing’] timer[2, ‘Processing’] timer[1:2, 4:6]
-
remove
(*keys)[source]¶ Remove a
Timer
.Note
- Remove from timers, not stack
- If key is string, then consider it as a label
- If key is integer or slice, then consider it as an index
- Key types can be mixed
-
walltime
()[source]¶ Compute walltime in seconds.
Only supported when all timers have completed, else error occurs.
-
tic
(key='')[source]¶ Start measuring time.
Measure time at the latest moment possible to not minimize noise from internal operations.
-
toc
(key=None)[source]¶ Stop measuring time.
Measure time at the soonest moment possible to not minimize noise from internal operations.
Note
- In cascade regions, that is, multiple toc() calls, some noise will be introduced. There is the possibility of correcting this noise, but even the correction is noise itself.
Timer Exceptions¶
-
class
smarttimer.timer.
TimerTypeError
(msg_or_name='', dtype=None)[source]¶ Exception for invalid data type assigment in
Timer
.
-
class
smarttimer.timer.
TimerValueError
(msg_or_name='', dtype=None)[source]¶ Exception for invalid values in
Timer
.