Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

timeit versus timing decorator

I'm trying to time some code. First I used a timing decorator:

#!/usr/bin/env python  import time from itertools import izip from random import shuffle  def timing_val(func):     def wrapper(*arg, **kw):         '''source: http://www.daniweb.com/code/snippet368.html'''         t1 = time.time()         res = func(*arg, **kw)         t2 = time.time()         return (t2 - t1), res, func.__name__     return wrapper  @timing_val def time_izip(alist, n):     i = iter(alist)     return [x for x in izip(*[i] * n)]  @timing_val def time_indexing(alist, n):     return [alist[i:i + n] for i in range(0, len(alist), n)]  func_list = [locals()[key] for key in locals().keys()              if callable(locals()[key]) and key.startswith('time')] shuffle(func_list)  # Shuffle, just in case the order matters  alist = range(1000000) times = [] for f in func_list:     times.append(f(alist, 31))  times.sort(key=lambda x: x[0]) for (time, result, func_name) in times:     print '%s took %0.3fms.' % (func_name, time * 1000.) 

yields

% test.py time_indexing took 73.230ms. time_izip took 122.057ms. 

And here I use timeit:

%  python - m timeit - s '' 'alist=range(1000000);[alist[i:i+31] for i in range(0, len(alist), 31)]' 10 loops, best of 3:     64 msec per loop % python - m timeit - s 'from itertools import izip' 'alist=range(1000000);i=iter(alist);[x for x in izip(*[i]*31)]' 10 loops, best of 3:     66.5 msec per loop 

Using timeit the results are virtually the same, but using the timing decorator it appears time_indexing is faster than time_izip.

What accounts for this difference?

Should either method be believed?

If so, which?

like image 391
unutbu Avatar asked Oct 26 '09 03:10

unutbu


People also ask

When would you use a function decorator?

You'll use a decorator when you need to change the behavior of a function without modifying the function itself. A few good examples are when you want to add logging, test performance, perform caching, verify permissions, and so on. You can also use one when you need to run the same code on multiple functions.

How does Timeit work Python?

What is Python Timeit()? Python timeit() is a method in Python library to measure the execution time taken by the given code snippet. The Python library runs the code statement 1 million times and provides the minimum time taken from the given set of code snippets.

What is a decorator in Python?

A decorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure. Decorators are usually called before the definition of a function you want to decorate.


1 Answers

Use wrapping from functools to improve Matt Alcock's answer.

from functools import wraps from time import time  def timing(f):     @wraps(f)     def wrap(*args, **kw):         ts = time()         result = f(*args, **kw)         te = time()         print 'func:%r args:[%r, %r] took: %2.4f sec' % \           (f.__name__, args, kw, te-ts)         return result     return wrap 

In an example:

@timing def f(a):     for _ in range(a):         i = 0     return -1 

Invoking method f wrapped with @timing:

func:'f' args:[(100000000,), {}] took: 14.2240 sec f(100000000) 

The advantage of this is that it preserves attributes of the original function; that is, metadata like the function name and docstring is correctly preserved on the returned function.

like image 182
Jonathan Prieto-Cubides Avatar answered Sep 21 '22 05:09

Jonathan Prieto-Cubides