Three four ways of measuring time in Python:
- start = time.time()
- timer()
- datetime.now()
- advanced profiling with cProfile
My personal favorite for simple time measurement of method is time. While for complex performance measurement I like to use cProfile which is giving comprehensive information on the price for several lines of code.
Measure time by module time
First way is by using module time. In this example we are calculating the 42-th Fibonacci number. We measure the time and print it out in ms, seconds and minutes
import time
def fib(i):
if i <= 2:
return 1;
else:
f = fib(i-1) + fib(i-2)
return f
start = time.time()
print(fib(42))
end = time.time()
execution_time = end - start
print ('--- %0.3fms. --- ' % ( execution_time*1000.))
print("--- %s seconds ---" % (execution_time ))
print("--- %s minutes ---" % (execution_time / 60))
result:
267914296
--- 92015.864ms. ---
--- 92.01586437225342 seconds ---
--- 1.533597739537557 minutes ---
Measure time by datetime
The same execution of Fibonacci measured by datetime module and returning the time in hh:mm:ss.ms
from datetime import datetime
def fib(i):
if i <= 2:
return 1;
else:
f = fib(i-1) + fib(i-2)
return f
start_time = datetime.now()
print(fib(42))
time_elapsed = datetime.now() - start_time
print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))
result:
267914296
Time elapsed (hh:mm:ss.ms) 0:01:32.943911
Measure time by datetime
Last example uses timeit and default_timer to test record the elapsed time.
from timeit import default_timer as timer
def fib(i):
if i <= 2:
return 1;
else:
f = fib(i-1) + fib(i-2)
return f
start = timer()
print(fib(42))
end = timer()
print("--- %s seconds ---", (end - start)/1.)
result:
267914296
--- %s seconds --- 93.60394597499999
Advanced profiling with cProfile
If you need to do more complex and better time measurement then you can use the module which offer Profiling - cProfile. It's mature and offers good results with few lines of code. Below we are measuring 3 methods:
- fib
- foo
- bar
As you can see from the result you have total time and separate time for each of this methods. Another advantage of the method is the information returned like:
- total calls of the method
- time spent total and per method
- line number of the method
You can see the example below testing Fibonacci with two additional functions:
import cProfile
def foo():
s = 0
for x in range(0, 1000):
s +=x
def bar():
s = 0
for x in range(0, 3000):
s +=x
def fib(i):
foo()
bar()
if i <= 2:
return 1;
else:
f = fib(i-1) + fib(i-2)
return f
cProfile.run('fib(20)')
result:
40590 function calls (27062 primitive calls) in 2.373 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 2.373 2.373 <string>:1(<module>)
13529/1 0.008 0.000 2.373 2.373 Profiling.py:14(fib)
13529 0.578 0.000 0.578 0.000 Profiling.py:4(foo)
13529 1.787 0.000 1.787 0.000 Profiling.py:9(bar)
1 0.000 0.000 2.373 2.373 {built-in method builtins.exec}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
What to use
As you can see the results for this 3 options are very close. The result depends on OS, running code, parallel execution. In order to get optimal results you need to do some test for your requirements. All these tests were done on Linux.