Python Timing Decorator

The two fundamental ways to measure performance are execution time and space.  When developing algorithms or processes, we want to try to have the fastest execution time and the smallest space requirements as possible.  Sometimes there may be tradeoffs where a little extra space will lead to faster execution times and vica versa. Typically, execution time is the measure that is generally focused on.

When we measure time, the easiest thing to do is take the current time, run the method or algorithm, then take the current time again.  Subtracting the two times will give a good estimate on the execution time of the method.  Though this logic is simple, it is often messy to add into your code.  With Python, we can make use of a decorator to produce clean, reusable code.

Additionally, when doing time measurements, we typically want to take an average of a number of runs.  The decorator will allow for this by adding a loops option to the decorator annotation.

The loops parameter takes an integer for the number of loops to run, 1 being the default.  The verbose parameter tells the decorator whether or not to print results every loop or not, False being the default.

The report given at the end of the timing run provides the min loop time, the max loop time, and the average loop time.

The decorator is written as follows

import time

def timeit(func=None,loops=1,verbose=False):
    if func != None:
        def inner(*args,**kwargs):

            sums = 0.0
            mins = 1.7976931348623157e+308
            maxs = 0.0
            print '====%s Timing====' % func.__name__
            for i in range(0,loops):
                t0 = time.time()
                result = func(*args,**kwargs)
                dt = time.time() - t0
                mins = dt if dt < mins else mins
                maxs = dt if dt > maxs else maxs
                sums += dt
                if verbose == True:
                    print '\t%r ran in %2.9f sec on run %s' %(func.__name__,dt,i)
            print '%r min run time was %2.9f sec' % (func.__name__,mins)
            print '%r max run time was %2.9f sec' % (func.__name__,maxs)
            print '%r avg run time was %2.9f sec in %s runs' % (func.__name__,sums/loops,loops)
            print '==== end ===='
            return result

        return inner
    else:
        def partial_inner(func):
            return timeit(func,loops,verbose)
        return partial_inner

Now we can decorate any method or function with this decorator and it will time its execution for us!

#This test will run a single time
@timeit
def test():
    time.sleep(0.25)

#This test will run 1000 times and average the times
@timeit(loops=1000)
def test2():
    time.sleep(0.25)

test()  #decorator prints: 'test' averaged 0.250000 sec in 1 runs
test2() #decorator prints: 'test2' averaged 0.250000 sec in 1000 runs

And it is that simple!

Share on Facebook+1Share on Twitter Share
Posted in Programming Tagged with: , , , ,
0 comments on “Python Timing Decorator
    1 Pings/Trackbacks for "Python Timing Decorator"
    1. […] ← Previous Next → […]

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    *

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">