SmartTimer Documentation¶
SmartTimers¶
SmartTimers is a collection of libraries for measuring runtime of running processes using a simple and flexible API. Time can be measured in sequential and nested code blocks.
A SmartTimer allows recording elapsed time in an arbitrary
number of code blocks. Specified points in the code are marked as either
the beginning of a block to measure, tic
, or as the end of a
measured block, toc
. Times are managed internally and ordered
based on tic
calls. Times can be queried, operated on, and
written to file.
- The following schemes are supported for timing code blocks
- Series:
tic('A')
,toc()
, …,tic('B')
,toc()
- Cascade:
tic('A')
,toc()
,toc()
, … - Nested:
tic('A')
,tic('B')
, …,toc()
,toc()
- Label-paired:
tic('A')
,tic('B')
, …,toc('A')
,toc('B')
- Mixed: arbitrary combinations of schemes
- Series:
from smarttimers import SmartTimer
# Create a timer instance named 'Example'
t = SmartTimer("Example")
# Print clock details
t.tic("info")
t.print_info()
t.toc()
# Measure iterations in a loop
t.tic("loop")
for i in range(10):
t.tic("iter " + str(i))
sum(range(1000000))
t.toc()
t.toc()
t.tic("sleep")
t.sleep(2)
t.toc()
# Write times to file 'Example.txt'
t.to_file()
print(t["info"])
print(t.walltime())
# Print times measured in different ways
>>> print(t)
label, seconds, minutes, rel_percent, cumul_sec, cumul_min,cumul_percent
info, 0.000270, 0.000004, 0.0001, 0.000270, 0.000004, 0.0001
loop, 0.153422, 0.002557, 0.0664, 0.153692, 0.002562, 0.0666
iter 0, 0.022840, 0.000381, 0.0099, 0.176531, 0.002942, 0.0765
iter 1, 0.023248, 0.000387, 0.0101, 0.199780, 0.003330, 0.0865
iter 2, 0.017198, 0.000287, 0.0074, 0.216977, 0.003616, 0.0940
iter 3, 0.012921, 0.000215, 0.0056, 0.229898, 0.003832, 0.0996
iter 4, 0.012754, 0.000213, 0.0055, 0.242652, 0.004044, 0.1051
iter 5, 0.012867, 0.000214, 0.0056, 0.255519, 0.004259, 0.1107
iter 6, 0.012843, 0.000214, 0.0056, 0.268361, 0.004473, 0.1162
iter 7, 0.012789, 0.000213, 0.0055, 0.281150, 0.004686, 0.1218
iter 8, 0.012818, 0.000214, 0.0056, 0.293969, 0.004899, 0.1273
iter 9, 0.012856, 0.000214, 0.0056, 0.306825, 0.005114, 0.1329
sleep, 2.002152, 0.033369, 0.8671, 2.308977, 0.038483, 1.0000
# Print stats only for labels with keyword 'iter'
>>> print(t.stats("iter"))
namespace(avg=(0.015313280202099122, 0.00025522133670165205),
max=(0.023248409008374438, 0.0003874734834729073),
min=(0.012753532995702699, 0.00021255888326171163),
total=(0.15313280202099122, 0.0025522133670165203))
MODULES¶
SmartTimer¶
-
class
smarttimers.smarttimer.
SmartTimer
(name='', **kwargs)[source]¶ Timer container to perform time measurements in code blocks.
Parameters: A
SmartTimer
allows recording elapsed time in an arbitrary number of code blocks. Specified points in the code are marked as either the beginning of a block to measure,tic()
, or as the end of a measured block,toc()
. Times are managed internally and ordered based ontic()
calls. Times can be queried, operated on, and written to file.- The following schemes are supported for timing code blocks
- Consecutive:
tic('A')
,toc()
, …,tic('B')
,toc()
- Cascade:
tic('A')
,toc()
,toc()
, … - Nested:
tic('A')
,tic('B')
, …,toc()
,toc()
- Label-paired:
tic('A')
,tic('B')
, …,toc('A')
,toc('B')
- Mixed: arbitrary combinations of schemes
- Consecutive:
-
name
¶ str – Name of container. May be used for filename in
write_to_file()
.
-
labels
¶ list, str – Label identifiers of completed timed code blocks.
-
active_labels
¶ list, str – Label identifiers of active code blocks.
-
seconds
¶ list, float – Elapsed time for completed code blocks.
-
minutes
¶ list, float – Elapsed time for completed code blocks.
-
times
¶ dict – Map of times elapsed for completed blocks. Keys are the labels used when invoking
tic()
.
-
__getitem__
(*keys)[source]¶ Query time(s) of completed code blocks.
Parameters: keys (str, slice, integer) – Key(s) to select times. If string, then consider it as a label used in tic()
. If integer or slice, then consider it as an index (based ontic()
ordering). Key types can be mixed.Returns: If key did not match a completed Timer label. list, float: Time in seconds of completed code blocks. Return type: None
-
tic
(label='')[source]¶ Start measuring time.
Measure time at the latest moment possible to minimize noise from internal operations.
Parameters: label (str) – Label identifier for current code block.
-
toc
(label=None)[source]¶ Stop measuring time at end of code block.
Note
In cascade regions, that is, multiple toc() calls, O(ms) noise will be introduced. In a future release, there is the possibility of correcting this noise, but even the correction is noise itself.
Parameters: label (str) – Label identifier for current code block. Returns: Measured time in seconds. Return type: float Raises: TimerError, KeyError – If there is not a matching tic()
.
-
walltime
()[source]¶ Compute elapsed time in seconds between first
tic()
and most recenttoc()
.walltime()
>= sum(seconds
)
-
remove
(*keys)[source]¶ Remove time(s) of completed code blocks.
Parameters: keys (str, slice, integer) – Key(s) to select times. If string, then consider it as a label used in tic()
. If integer or slice, then consider it as an index (based ontic()
ordering). Key types can be mixed.
-
dump_times
(filename=None, mode='w')[source]¶ Write timing results to a file.
If filename is provided, then it will be used as the filename. Otherwise
name
is used if non-empty, else the default filename is used. The extension .times is appended only if filename does not already has an extension. Using mode the file can be overwritten or appended with timing data.Parameters: - filename (str, optional) – Name of file.
- mode (str, optional) – Mode flag passed to open. Default is w.
-
stats
(label=None)[source]¶ Compute total, min, max, and average stats for timings.
Note
- An alphanumeric label is used as a word-bounded regular expression.
- A non-alphanumeric label is compared literally.
- If label is ‘None’ then all completed timings are used.
Parameters: label (str, iterable, optional) – String/regex used to match timer labels to select. Returns: Namespace with stats in seconds/minutes. Return type: types.SimpleNamespace
-
to_array
()[source]¶ Return timing data as a list or numpy array (no labels).
Data is arranged as a transposed view of
__str__()
andto_file()
formats.Returns: Timing data. Return type: numpy.ndarray, list
-
dump_profile
(filename=None, mode='w')[source]¶ Write profiling results to a file.
If filename is provided, then it will be used as the filename. Otherwise
name
is used if non-empty, else the default filename is used. The extension .prof is appended only if filename does not already has an extension. Using mode the file can be overwritten or appended with timing data.Parameters: - filename (str, optional) – Name of file.
- mode (str, optional) – Mode flag passed to open. Default is w.
Timer¶
-
class
smarttimers.timer.
Timer
(label='', **kwargs)[source]¶ Read current time from a clock/counter.
Parameters: - label (str, optional) – Label identifier. Default is empty string.
- kwargs (dict, optional) – Map of options. Valid options are
seconds
,clock_name
, andtimer
. - 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 (Timer, optional) – Reference instance to use as 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.Timer API examples.¶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 smarttimers 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() (deprecated)
- ‘monotonic’ -> time.monotonic()
- ‘time’ -> time.time() (deprecated)
Registering a new time measurement function.¶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.
-
DEFAULT_CLOCK_NAME
¶ str – Default clock name, used when
clock_name
is empty string.Raises: TypeError
– If not a string.
-
CLOCKS
¶ TimerDict
, str -> callable – Map between clock name and time measurement functions.Raises: TypeError
– If not assigned with dictionary.KeyError
– If key is not a string.ValueError
– If assigned item is not callable.
-
label
¶ str – Label identifier.
Raises: TypeError
– If not a string.
-
seconds
¶ float, read-only – Time measured in fractional seconds.
Set internally either during initialization or when recording time.
Raises: TypeError
– If not numeric.ValueError
– If negative number.
-
minutes
¶ float, read-only – Time measured in minutes.
-
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: TypeError
– If not a string.
-
time
(*args, **kwargs)[source]¶ Record time using timing function configured via
clock_name
.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.
Returns: Namespace with clock info. Return type: types.SimpleNamespace
-
is_compatible
(timer)[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. Otherwise the timing functions have to be the same.Parameters: timer (Timer) – Second instance. Returns: True if compatible, else False. Return type: bool
-
classmethod
register_clock
(clock_name, clock_func)[source]¶ Registers a time function to
CLOCKS
map.Parameters: - clock_name (str) – Clock name.
- clock_func (callable) – Reference to a time measurement function.
Decorators¶
SmartTimer decorators
- Functions:
time()
-
smarttimers.decorators.
time
(func=None, *, timer=None)[source]¶ Measure runtime for functions/methods.
Parameters: timer (SmartTimer, optional) – Instance to use to measure time. If None, then global SmartTimer instance, _timer, is used.
HISTORY¶
v1.3.0¶
Date: | 2018-12-3 |
---|
- Features:
- SmartTimer: new stats() to compute total, min, max, and avg statistics.
- SmartTimer: label support for toc() in cascade scheme.
- SmartTimer: new relative and cumulative time data.
- SmartTimer: new to_array() to transform timing data to list/numpy array (numpy is optional).
- Timer, SmartTimer: added sleep().
- README: minor update to examples.
- Tests: updated some cases to support SmartTimer changes.
- Exceptions: error messages are given explicitly when raised.
v1.0.0¶
Date: | 2018-11-29 |
---|
- Features:
- SmartTimer: complete test cases.
- SmartTimer: consistent API behavior.
- Added basic documentation and example in README.
- Update configuration files.
v0.9.5¶
Date: | 2018-11-28 |
---|
- Features:
- Changed package name to smarttimers.
- SmartTimer: complete documentation.
- SmartTimer: added example.
- SmartTimer: improved exception handling.
- Bug fixes:
- SmartTimer: walltime is calculated from first tic until most recent toc.
- SmartTimer: name attribute cannot be set to empty string.
v0.9.0¶
Date: | 2018-11-26 |
---|
- Features:
- SmartTimer: time lists maintain ordering relative to tic() calls.
- SmartTimer: support for consecutive, nested, cascade, interleaved, and key-paired code blocks.
- Improved error handling and exceptions raised.
- Bug fixes:
- SmartTimer: changed times() to use new labels() output format.
v0.8.5¶
Date: | 2018-11-25 |
---|
- Features
- SmartTimer: implemented container for tic-toc support.
- Improved module dependencies for setup, tests, and docs.
- Code style is compliant with flake8.
v0.6.0¶
Date: | 2018-11-22 |
---|
- Features
- Timer: time values are read-only.
- Timer: new clear, reset, (un)register_clock methods.
- Timer: new custom exception classes and improved exception handling.
- Timer: rename sum, print_info, and print_clocks methods.
- Timer: complete documentation.
- Timer: complete test cases.
- Integrated tox, Travis CI, code coverage, and Read the Docs.
- Cleaned code adhering to flake8.
v0.4.0¶
Date: | 2018-11-19 |
---|
- Features
- Timer: new print/get_clock_info methods.
- Timer: improved compatibility checks.
- Timer: new TimerCompatibilityError exception.
- Timer: documentation revision.
v0.3.0¶
Date: | 2018-11-18 |
---|
- Features
- Timer: include an example script.
- Timer: new MetaTimerProperty and TimerDict for handling class variable properties.
- Timer: improved exception coverage.
- Timer: improved methods for checking compatibility and print clock info.
- Timer: time values are cleared automatically when clock name is changed.
v0.2.2¶
Date: | 2018-11-18 |
---|
- Features
- Timer: new methods to print clock details using time.get_clock_info.
- Timer: updated docstrings and provide usage examples.
v0.2.0¶
Date: | 2018-11-17 |
---|
- Features
- Timer: new methods to support sum, difference, and comparison operators.
- Timer: new methods to check compatibility between Timers.
CONTRIBUTING¶
All types of contributions are welcomed. A guide for developers will be made available soon.
- Meanwhile:
- Clone repository
- Make improvements
- Fix bugs
- Make pull requests
CREDITS¶
Many thanks to all people who have provided useful feedback and recommendations during the development of SmartTimer. These credits use a convention based on Linux CREDITS where the fields are: name (N), email (E), web-address (W), country (C), description (D), issues (I).
Author¶
N: Eduardo Ponce
E: edponce2010@gmail.com
W: https://github.com/edponce
C: TN, USA
D: Lead developer
LICENSE¶
Copyright 2018 Eduardo Ponce
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.