42. timer — Timer: Measuring elapsed time.

Note

Contrary to its use in plain English, we use the word ‘timer’ here for a device that measures the time between two events, not one that counts down a given amount of time.

The Timer class provides a convenient way to measure the time between two events. When developing algorithms for operations on large data models, accurate and multiple measurements of the time spent in different parts of the code are a vital accessory. The Timer class aims at making the process of measuring and reporting as simple is possible for a variety of uses. The following examples illustrate the most common use cases.

Examples

We use time.sleep() to provide a dummy code block with some known execution time.

>>> from time import sleep

The example below shows the three basic steps: create a timer, make a measurement, report the result. A Timer instance acts as a context manager, so it can be used in a with statement. The time spent in the block inside the with clause is then measured.

>>> t = Timer()      # 1. create a Timer
>>> with t:          # 2. measure the time for a code block
...     sleep(0.07)
>>> print(t)         # 3. report the measured time
Timer: 0.07... sec. Acc: 0.07... sec.

Notice that two values are printed out: the first is the measured time, the second is the accumulated time of all measurements with this timer. Let’s add a second measurement:

>>> sleep(0.05)
>>> with t:
...     sleep(0.06)
>>> print(t)
Timer: 0.06... sec. Acc: 0.13... sec.

Notice that only the time inside the with block is measured. Printing out the Timer after measurement is so common, that there is an option to do it automatically. Just set the auto mode on (this can also be given as an option when creating the Timer).

>>> t.auto = True
>>> with t:
...     sleep(0.03)
Timer: 0.03... sec. Acc: 0.16... sec.

If you do not need the accumulation feature, you can switch it off by setting acc=None. We create a new Timer t1, with appropriate tag. The tag is the string printed before the timer values (the default tag is ‘Timer’):

>>> with Timer('No accumulation', auto=True, acc=None) as t1:
...     sleep(0.07)
No accumulation: 0.07... sec.
>>> with t1: sleep(0.13)
No accumulation: 0.13... sec.

You can specify the precision of the output (the actual readings are still done at the highest precision):

>>> t2 = Timer('Precision 2', dec=2, auto=True)
>>> with t2: sleep(0.057)
Precision 2: 0.06 sec. Acc: 0.06 sec.
>>> with t2: sleep(0.093)
Precision 2: 0.09 sec. Acc: 0.15 sec.

When using multiple timers it is often convenient to be able to use a single variable to keep all Timer instances alive, or to print all the timers at once. The Timers class provides a list of Timer instances to allow that.

>>> timers = Timers(t, t1, t2)
>>> print(timers)
Timer report
  Timer: 0.03... sec. Acc: 0.16... sec.
  No accumulation: 0.13... sec.
  Precision 2: 0.09 sec. Acc: 0.15 sec.
>>> print(len(timers))
3

Plain list methods can be used on the Timers class, but you shouldn’t add anything but Timer instances. The get() method retrieves a Timer by its tag. If multiple timers have the same tag, you can only get the first one.

>>> print(timers.get('No accumulation'))
No accumulation: 0.13... sec.
>>> t3 = Timer('Precision 2')
>>> timers.append(t3)
>>> print(len(timers))
4
>>> timers.get('Precision 2') is t3
False
>>> timers.get('Precision 2') is t2
True
>>> timers.clear()
>>> print(len(timers))
0

Timer context managers can be nested, so one can easily do partial and overall timings at the same time:

>>> with Timer("Outer block", dec=2, reg=timers):
...    sleep(0.08)
...    with Timer("Inner block", dec=2, reg=timers):
...        sleep(0.12)
...    sleep(0.07)
...    with Timer("Inner block 2", dec=2, reg=timers):
...        sleep(0.17)
...    sleep(0.06)
...
>>> print(timers)
Timer report
  Outer block: 0.50 sec. Acc: 0.50 sec.
  Inner block: 0.12 sec. Acc: 0.12 sec.
  Inner block 2: 0.17 sec. Acc: 0.17 sec.

The output of the above on some machine gave:

Process time: 0.02... sec. Acc: 0.02... sec.
Real time: 0.08... sec. Acc: 0.08... sec.

There may be times when the use of a context manager is not useful or even possible (like when the start and end of measurement are in different functions). Then you can always use the low level interface. The measurement is always done with the read() method. It measures and returns the time since the last start() or the creation of the Timer. Here is an example:

>>> t = Timer(dec=2)
>>> sleep(0.03)
>>> v = t.read()
>>> sleep(0.05)
>>> t.start()
>>> sleep(0.07)
>>> v1 = t.read()
>>> print(v, v1)
0.03... 0.07...

The last reading and the accumulated value remain accessible for further processing or customized reports:

>>> print(t2.mem, t2.acc)
0.09... 0.15...
>>> print(f"'{t2.tag}' timer: last read {t2.mem}"
...       f", accumulated {t2.acc}")
'Precision 2' timer: last read 0.09, accumulated 0.15

You can have a peek at the current value of the timer, without actually reading it, and thus not chainging the timer’s memory:

>>> print(t)
Timer: 0.07 sec. Acc: 0.10 sec.
>>> sleep(0.09)
>>> print(t.value)
0.09...
>>> print(t)
Timer: 0.07 sec. Acc: 0.10 sec.

Measuring process time is easy as well. Just provide another time measuring function:

>>> timers = Timers(
...     Timer('Real time', auto=True, dec=2, acc=None),
...     Timer('Process time', auto=True, acc=None, timefunc=time.process_time)
... )
>>> with timers:
...     _ = [i*i for i in range(10_000)]  # do something
...     sleep(0.06)
Process time: 0.00... sec.
Real time: 0.06 sec.

42.1. Classes defined in module timer

class timer.Timer(tag='Timer', *, timefunc=<built-in function perf_counter>, dec=6, acc=0.0, auto=False, reg=None)[source]

A class for measuring elapsed time.

The Timer class is a conventient way to measure and report the elapsed time during some processing. It uses Python’s time.perf_counter(), providing the highest resolution available. It is however not intended for doing micro measurements: use Python’s timeit module for that.

A Timer instance can be used as a context manager, with automatic reading and even reporting the time spent in the context block. The Timer value is a floating point value giving a number of seconds elapsed since some undefined reference point. By default this is the moment of creation of the Timer, but the starting point can be set at any time.

Parameters:
  • tag (str, optional) – A label identifying the Timer. It is shown together with the time value when printing the Timer. It is also used as the key when registering a Timer.

  • timefunc (callable, optional) – A callable returning a float. The difference in value between two calls is the measured time in seconds. The default time.perf_counter() measures real time with high precision. Some other useful values: time.time(), time.monotonic(), time.process_time(), time.thread_time().

  • dec (int, optional) – The number of decimals that will be shown when printing the Timer. The default (6) provides microsecond accuracy, which is more than enough for all purposes.

  • acc (float | None, optional) – Starting value for the accumulator. When a Timer is read, it accumulates the value in its acc attribute. The accumulted value is printed out together with the reading. A special value None may be provided to switch off the accumulator.

  • auto (bool, optional) – If True, switches on auto print mode for the Timer. In auto print mode, the value of the Timer is printed out on each read() and, when using a context manager, on exiting it. This is very convenient to quickly do timing of some code block. See the examples above. If False, the user is responsible for printing out the Timer.

  • reg (Timers, optional) – If a Timers instance is provided, the new Timer is added to that collection and its value can be printed out together with that of the others in the collection.

property value

The current value of the Timer.

Peeking at the Timer’s value does not read() the Timer.

property mem

The last read value rounded to the timer’s precision.

Note

Use _mem to get the full precision.

property acc

The accumulator value rounded to the timer’s precision.

Note

Use _acc to get the full precision.

property tag

The timer’s tag string

newtag(newtag)[source]

Change the tag string of the Timer.

Returns:

self – The Timer itself, thus this method can be used as a context manager.

start()[source]

Start the timer.

This marks the start for the next read() operation.

read()[source]

Read the timer.

Read the time since the last read() or start(), or since the creation of the Timer. Store the time in self.mem, and accumulate it in self.acc (if not None). Print the Timer if auto mode is on.

Returns:

float – The time in seconds since the last read() or start(), or since the creation of the Timer.

format()[source]

Return a string representation of the Timer.

Returns:

string – A string with the Timer’s tag, the last read value, and the accumulated value if the Timer is an accumulating one. This is also the string that will be shown when printing a Timer.

class timer.Timers(*timers)[source]

A collection of timers

Timers is a list of Timer instances. All normal list methods are available. Thould take care though to add nothing but Timer instances to the list.

The benefits over using a plain list is that printing a Timers will give a nicely formatted output of the timers and that the Timers can be used as a content manager to activate all its Timer instances at once. The latter is e.g. convenient to measure the same code block with different time functions.

Parameters:

*timers (optional) – A sequence of Timer instances.

get(tag)[source]

Return the (first) timer in the list with the specified tag

Parameters:

tag (str) – The tag string of a Timer to be found in the Timers list.

Returns:

Timer | None – If the tag was found in the list, returns the first matching Timer. Else, returns None.

report(*tags)[source]

Return a full report of all existing or requested Timers.

Parameters:

*tags (sequence, optional) – A sequence of tag strings of the timers that should be included in the report. In none provided, all timers are included.

Returns:

string – A string containing the formatted Timer instances. This is also the string that will be shown by the print function.