Timing#
Timing is the act of measuring the execution time of a program. It’s a crucial step to learn where a program is taking most time and/or resources, so you can focus on trying to optimize those parts.
Unix time#
On the Unix shell you can prefix any command with time
to measure its runtime. As illustration, consider we want to measure how long it takes to fetch a given web page.
$ time https example.com > /dev/null
real 0m0.707s
user 0m0.162s
sys 0m0.046s
Three different time intervals are returned that we need to distinguish.
real
: is the wall-clock time, so the total time that elapsed from start to finish of the program.user
: is the amount of time the CPUs spent in user-mode to execute the program’s code.sys
: is the amount of time the CPUs spent running syscalls in kernel-mode (eg memory allocation or file I/O).
The sum user+sys
is the total time the program was using the CPUs. When running concurrent code on multi-core systems this sum typically exceeds the real
elapsed time.
In our example user+sys
is only a small fraction of the real
time because most of the runtime is spent waiting for the response of the remote web server. As we will later see, this is a prime example of code that can have a high speed-up with parallel execution.
See also
Be attentive that the runtime may vary between subsequent executions of the same code. Typically the second run is faster than the first because of caching. As usual it’s important to repeat the measurement and gather some statistics to make meaningful statements. Tools like hyperfine can help with such benchmarks.
Python time#
The time module allows to measure execution time inside Python code. We use the performance counter perf_counter_ns()
which returns an integer representing “current” time in nanoseconds. Note that the reference point of the returned time is undefined, so that only time differences are meaningful.
import time
t0 = time.perf_counter_ns() # start time in nanoseconds (as integer)
time.sleep(1) # sleep to simulate time-consuming code
t1 = time.perf_counter_ns() # end time
print(f"elapsed time: {t1 - t0} ns")
timeit#
Having already encountered timeit
as magic command of IPython, we now turn to the actual timeit module of Python standard library. It allows to time snippets of Python code and can, among others, be called directly with its command-line interface.
$ python -m timeit '"-".join(str(n) for n in range(100))'
50000 loops, best of 5: 4.6 usec per loop
As seen from the output, timeit automatically looped over the same snippet to execute it multiple times and gather some statistics on its runtime.