Profiling weirdness: Timer.timeit(), fibonacci and memoization

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Aug 3 00:05:07 EDT 2008


On Sat, 02 Aug 2008 16:14:11 -0500, Rob Williscroft wrote:

> Stefaan Himpe wrote in news:2m3lk.118118$9I1.20910 at newsfe16.ams2 in
> comp.lang.python:
> 
>> Nothing weird about this ...
>> The difference will become larger as your input value becomes larger.
>> 
>> You can easily understand why if you try to calculate fib(10) by hand,
>> i.e. work through the algorithm with pencil and paper, then compare the
>> work you have to do to the memoized version which just takes fib(9) and
>> fib(8) from memory and adds them together.
>> 
>> 
> I think you missed the point.
> 
> The problem is that the un-decorated, loop only version takes 35 seconds
> when called by timeit.Timer.  However if you apply the decorator it
> takes less that a second.  In *both* cases the function (fib) only gets
> called once.

I think you are completely misreading the results of the Timeit calls. 
That's not correct: you're calling it one million times, not once.

You should apply a "sanity check" to results. At the interactive console, 
call the undecorated fib(100) once. Does it take 35 seconds? If so, your 
computer is terribly slow -- on mine, it returns instantly.

Note that in your email, you showed only half the output:


[quote]
t1 = Timer('fib(s)', 'from __main__ import fib, s')
t2 = Timer('fibmem(s)', 'from __main__ import fibmem, s')
t1.repeat(number=1)
t2.repeat(number=1)
print t1.timeit()
print t2.timeit()


>>>
35.3092010297
1.6516613145
[end quote]

You had two calls to Timer.repeat() methods, and you didn't show the 
output. *They* call the Fibonacci functions once. When I do that, I get 
output looking like this:

>>> t1 = Timer('fib(s)', 'from __main__ import fib, s')
>>> t1.repeat(number=1)
[7.9870223999023438e-05, 5.5074691772460938e-05, 5.4121017456054688e-05]

You then call the Timer.timeit() method, which calls the function one 
million times by default. That's the output you show: notice that 35s 
divided by one million is 3.5e-05s, around what I get using the repeat() 
method. There's no mystery.


> Note, I timed the call fib(100) with time.clock() and got a value of
> less than 1 ms, the memozed version takes about 10 times longer.

You shouldn't give much credence to timing results from calling a 
function once (unless the function does a *lot* of work). Your operating 
system is doing all sorts of work in the background. It can easily 
interrupt your process mid-calculation to do something else, and your 
timing code will then include that. You'll then wrongly conclude that the 
function is slower than it really is.

Also, keep in mind that time.clock() is likely to be significantly less 
accurate if you are using Linux. The timeit module automatically choose 
the best function to use (time.clock vs time.time) for you.

> So the question is: whats going on with timeit.Timer ?

As far as I can see, nothing. I think you have misunderstood the results 
you got.



-- 
Steven



More information about the Python-list mailing list