472,328 Members | 2,084 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,328 software developers and data experts.

Timing a function object versus timeit

The timeit module is ideal for measuring small code snippets; I want to
measure large function objects.

Because the timeit module takes the code snippet argument as a string, it
is quite handy to use from the command line, but it is less convenient for
timing large pieces of code or when working in the interactive
interpreter. E.g. variations on this *don't* work:

$ python
Python 2.4.3 (#1, Jun 13 2006, 11:46:08)
[GCC 4.1.1 20060525 (Red Hat 4.1.1-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
def foo(x):
.... return x+1
....
>>assert foo(1) == 2 # do lots of interactive testing

import timeit
timeit.Timer("foo(1)").timeit()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/lib/python2.4/timeit.py", line 161, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
NameError: global name 'foo' is not defined
>>>
One solution is to work like this:
>>foo_str = """def foo(x):
.... return x+1
.... """
>>exec foo_str
assert foo(1) == 2
timeit.Timer("foo(1)", foo_str).timeit(10000)
0.006793975830078125

Not so useful if you are timing functions from existing code, and very
easy to get foo_str and foo out of sync.

One solution is to resign oneself that timeit is just no good for timing
actual function objects, and to resort to writing ad hoc and potentially
buggy timing code any time you want to time a function:
>>import time
def timer(n=10000):
.... _it = [None]*n
.... t = time.time()
.... for _ in _it:
.... foo(1)
.... t = time.time() - t
.... return t
....
>>timer()
0.0082669258117675781

That's hardly best practice -- good enough for rough and ready "how fast
is this?" but not scalable beyond one or two functions.

Do others have other suggestions or techniques they use?
I thought I could write a function, similar to the timeit.Timer.timeit()
method, which would take a function object instead of a string, plus
arbitrary arguments, and carefully time how long it takes to execute. I
ended up with something like this:

def ftimer(func, args, kwargs, number=1000000, timer=time.time):
it = itertools.repeat(None, number)
gc_saved = gc.isenabled()
gc.disable()
t0 = timer()
for i in it:
func(*args, **kwargs)
t1 = timer()
if gc_saved:
gc.enable()
return t1 - t0

(Aside: I should put the timing code in a try block, with the gc
restoration code under finally. Next version.)

Much to my surprise, this seems to give me elapsed times about double that
of timeit, at least for small functions that do little work.

I expected that executing the function would be faster than the timeit
module, which goes to show how badly off my intuition regarding the
overhead of timeit was.

I presume the problem is that the time it takes to unroll the *args and
**kwargs is making a significant difference to the time taken. But even if
I remove those arguments, and just call functions that take no arguments,
there is still a significant difference. My ftimer results are
consistently 10-20% longer than timeit. Example:
>>setup_null = """def null():
.... return
.... """
>>exec setup_null
timeit.Timer("null()", setup_null).timeit()
0.7631678581237793
>>ftimer(null, [], {})
1.8860080242156982
>>ftimer2(null) # version that doesn't pass *args and **kwargs
0.90903997421264648
Can anyone help me understand these results? Why is the overhead
associated with timeit apparently so much smaller than the overhead in my
ftimer functions?

Am I barking up the wrong tree here? Is there a flaw in my reasoning, and
I'm measuring execution time the wrong way?

Or is it that the timeit module and my ftimer functions are measuring
subtly different things?

--
Steven.

Nov 4 '06 #1
2 3190

Steven D'Aprano wrote:
The timeit module is ideal for measuring small code snippets; I want to
measure large function objects.

Because the timeit module takes the code snippet argument as a string, it
is quite handy to use from the command line, but it is less convenient for
timing large pieces of code or when working in the interactive
interpreter. E.g. variations on this *don't* work:
[snip]
Do others have other suggestions or techniques they use?

Python 2.4.3 (#2, Jun 19 2006, 12:51:44)
[GCC 4.0.3 20060212 (prerelease) (Debian 4.0.2-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>def foo(x):
.... return x+1
....
>>import timeit
timeit.Timer("foo(1)","from __main__ import foo")
1.1497418880462646
Carl Banks

Nov 4 '06 #2
On Fri, 03 Nov 2006 18:02:37 -0800, Carl Banks wrote:
>>>import timeit
timeit.Timer("foo(1)","from __main__ import foo")
1.1497418880462646

Well, that was scarily simple.

Thank you.
--
Steven.

Nov 4 '06 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Jacek Generowicz | last post by:
Given fncs = args = How should one spell results = map(lambda f,a: f(a), fncs, args) in order to get the result most quickly ?
5
by: flupke | last post by:
Hi, i tried to use timeit on a function in a class but it doesn't do what i think it should do ie. time :) In stead it starts printing line...
7
by: Steven D'Aprano | last post by:
I have two code snippets to time a function object being executed. I expected that they should give roughly the same result, but one is more than...
11
by: Russ | last post by:
I have a couple of questions for the number crunchers out there: Does "pow(x,2)" simply square x, or does it first compute logarithms (as would...
2
by: kevin | last post by:
Hi... I'm having a few problems here... I want to input in my function different values and then time each one to see how long it took to run the...
27
by: idoerg | last post by:
Hi all, I am running Python 2.5 on Feisty Ubuntu. I came across some code that is substantially slower when in a method than in a function. ...
3
by: David | last post by:
Hi, In matlab, I'd calculate the time for a script named test.m to run with: Is there some way to do this in python on a mac os x from the...
5
by: Steven D'Aprano | last post by:
After reading an earlier thread about opening and closing lots of files, I thought I'd do a little experiment. Suppose you have a whole lot of...
0
by: Daniel Fetchinson | last post by:
On 4/15/08, Daniel Fetchinson <fetchinson@googlemail.comwrote: BTW, using the following ...
0
by: tammygombez | last post by:
Hey fellow JavaFX developers, I'm currently working on a project that involves using a ComboBox in JavaFX, and I've run into a bit of an issue....
0
by: tammygombez | last post by:
Hey everyone! I've been researching gaming laptops lately, and I must say, they can get pretty expensive. However, I've come across some great...
0
better678
by: better678 | last post by:
Question: Discuss your understanding of the Java platform. Is the statement "Java is interpreted" correct? Answer: Java is an object-oriented...
0
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
0
by: CD Tom | last post by:
This happens in runtime 2013 and 2016. When a report is run and then closed a toolbar shows up and the only way to get it to go away is to right...
0
jalbright99669
by: jalbright99669 | last post by:
Am having a bit of a time with URL Rewrite. I need to incorporate http to https redirect with a reverse proxy. I have the URL Rewrite rules made...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. ...
1
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.