dpdt
dpdt

Reputation: 113

Timing Code Execution Time

So, I am interested in timing some of the code I am setting up. Borrowing a timer function from the 4th edition of Learning Python, I tried:

import time
reps = 100
repslist = range(reps)

def timer(func):
    start = time.clock()
    for i in repslist:
        ret = func()
    elasped = time.clock()-start
    return elapsed

Then, I paste in whatever I want to time, and put:

print(timer(func))    #replace func with the function you want to time

When I run it on my code, I do get an answer, but it's nonsense. Suspecting something was wrong, I put a time.sleep(0.1) call in my code, and got a result of 0.8231

Does anybody know why this might be the case or how to fix it? I suspect that the time.clock() call might be at fault.

Upvotes: 1

Views: 966

Answers (4)

ShadowRanger
ShadowRanger

Reputation: 155333

After fixing the typo in the first intended use of elapsed, your code works fine with either time.clock or time.time (or Py3's time.monotonic for that matter) on my Linux system.

The difference would be in the (OS specific) behavior for clock; on most UNIX-like OSes it will return the processor time used by the program since it launched (so time spent blocked, on I/O, locks, page faults, etc. wouldn't count), while on Windows it's a wall clock timer (so time spent blocked would count) that counts seconds since first call.

The UNIX-like version of time.clock is also fairly unreliable if used in a long running program when clock_t is only 32 bits; the value it returns will wrap roughly every 72 minutes of processor time.

Of course, time.time isn't perfect either; it follows the system clock, so an NTP time update (or any other change to the system clock) occurring between calls will give erroneous results (on Python 3.3+, you'd use time.monotonic to avoid this problem). It's also not guaranteed to have granularity finer than 1 second, so if your function doesn't take an awfully long time to run, on a system with low res time.time you won't get particularly useful results.

Really, you should be looking at the Python batteries designed for this (that also handle issues like garbage collection overhead and the like). The timeit module already has a function that does what you want, but handles all the edge cases and issues I mentioned. For example, to time some global function named foo for 100 reps, you'd just do:

import timeit

def foo():
    ...

print(timeit.timeit('foo()', 'from __main__ import foo', number=100))

It fixes most of the issues I mention by selecting the best timing function for the OS you're on (and also fixes other sources of jitter, e.g. cyclic garbage collection, which is disabled during the test and reenabled at the end).

Even if you don't want to use that for some reason, if you're using Python 3.3 or higher, take a look at the replacements for time.clock, e.g. time.perf_counter (includes time spent sleeping) or time.process_time (includes only CPU time), both of which are portable, reliable, fast, and high resolution for better accuracy.

Upvotes: 0

miguels
miguels

Reputation: 636

If you want to timer a function perhaps give decorators a try(documentation here):

import time

def timeit(f):    
    def timed(*args, **kw):
        ts = time.time()
        result = f(*args, **kw)
        te = time.time()
        print 'func:%r args:[%r, %r] took: %2.4f sec' % \
          (f.__name__, args, kw, te-ts)
        return result
    return timed

Then when you write a function you just use the decorator, here:

@timeit
def my_example_function():
    for i in range(10000):
        print "x"

This will print out the time the function took to execute:

func:'my_example_function' args:[(), {}] took: 0.4220 sec

Upvotes: 1

Kevin
Kevin

Reputation: 76184

According to the help docs for clock:

Return the CPU time or real time since the start of the process or since the first call to clock(). This has as much precision as the system records.

The second call to clock already returns the elapsed time between it and the first clock call. You don't need to manually subtract start.

Change

elasped = time.clock()-start

to

elasped = time.clock()

Upvotes: 2

ssm
ssm

Reputation: 5373

The time.sleep() will terminate for any signal. read about it here ...

http://www.tutorialspoint.com/python/time_sleep.htm

Upvotes: -1

Related Questions