0

need help for this code

import timeit

mysetup=""

mycode='''

def gener():
 ...my code here...
 return x
 '''

# timeit statement
print (timeit.timeit(setup = mysetup,
                    stmt = mycode,
                    number = 1000000))

print("done")

As result I got 0.0008606994517737132 As I read this unit is in "seconds" So my funtion executed 1 million time in 0.8 ms ? I think this is not real, too fast.

I also tried basic option

start = time.time()
my code here
end = time.time()
print(end - start)

and got 0.23901081085205078 for one time execution it seems a little slow...

So what I'm I doing wrong ? Thanks

hughes
  • 177
  • 1
  • 5
  • 11
  • 3
    Is your code actually just defining the function `gener`, not calling it? Then you are just measuring how fast python can parse this function, not how fast it runs. – YSelf Dec 14 '17 at 10:01
  • Hi, timeit is supposed to call my function <> 1 million time... – hughes Dec 14 '17 at 14:34

4 Answers4

2

The way you have defined this in mycode for the timeit method, all that is going to happen is the function gener will be defined, not run. You need to run the function in your code block in order to report time taken for execution.

As for what length of time is reasonable (too fast/too slow) it very much depends on what your code is doing. But I suspect you have executed the function in method 2 and only defined it in method 1, hence the discrepancy.

Edit: example code

To illustrate the difference, in the example below the block code1 just defines a function, it does not execute it. The block code2 defines and executes the function.

import timeit

code1 = '''
def gener():
    time.sleep(0.01)
'''

code2 = '''
def gener():
    time.sleep(0.01)
gener()
'''

We should expect running time.sleep(0.01) 100 times to take approximately 1 second. Running timeit for code1 returns ~ 10^-5 seconds, because the function gener is not actually being called:

timeit.timeit(stmt=code1, number=100)

Running timeit for code2 returns the expected result of ~1 second:

timeit.timeit(stmt=code2, number=100)

Further to this, the point of the setup argument is to do setup (the parts of the code which are not meant to be timed). If you want timeit to capture the execution time of gener, you should use this:

import timeit

setup = '''
def gener():
    time.sleep(0.01)
'''

stmt = "gener()"

timeit.timeit(setup=setup, stmt=stmt, number=100)

This returns the time taken to run gener 100 times, not including the time taken to define it.

Simon Bowly
  • 1,003
  • 5
  • 10
  • Ok... do you understand my answer? I've added an example which hopefully helps you understand what's going on. Suggest you read the docs for [timeit](https://docs.python.org/3.6/library/timeit.html) – Simon Bowly Dec 15 '17 at 06:44
  • Yes I understand now, timeit was not running my function in the example. The real code seen by timeit is: start clock `setup stmt stmt stmt stmt stmt ...` Stop clock And there was any execution of the code in setup or stmt. In fact it is like a inline function in C++ defined multiple time, and never executed. – hughes Dec 17 '17 at 14:39
1

Here is a general way to measure time of code snippets.

import time
class timer(object):
    """
        A simple timer used to time blocks of code. Usage as follows:

        with timer("optional_name"):
            some code ...
            some more code
    """
    def __init__(self, name=None):
        self.name = name

    def __enter__(self):
        self.start = time.time()
        return self

    def __exit__(self, *args):
        self.end = time.time()
        self.interval = self.end - self.start
        if self.name:
            print("{} -  Elapsed time: {:.4f}s".format(self.name, self.interval))
        else:
            print("Elapsed time: {:.4f}s".format(self.interval))

gist available here: https://gist.github.com/Jakobovski/191b9e95ac964b61e8abc7436111d1f9

Jakobovski
  • 3,203
  • 1
  • 31
  • 38
0

If you want to time a function timeit can be used like so:

# defining some function you want to time
def test(n):
    s = 0
    for i in range(n):
        s += i
    return s

# defining a function which runs the function to be timed with desired input arguments
timed_func = lambda : test(1000)

# the above is done so that we have a function which takes no input arguments

N = 10000 # number of repeats
time_per_run = timeit.timeit(stmt=timed_func, number=N)/N

For your case you can do:

# defining some function you want to time
def gener():
    ...my code here...
    return x

N = 1000000 # number of repeats
time_per_run = timeit.timeit(stmt=gener, number=N)/N

Any importing of libraries can be done globally before calling the timeit function and timeit will use the globally imported libraries

e.g.

import numpy as np

# defining some function you want to time
def gener():
    ...my code here...
    x = np.sqrt(y)
    return x


N = 1000000 # number of repeats
time_per_run = timeit.timeit(stmt=gener, number=N)/N
SomeRandomPhysicist
  • 1,531
  • 4
  • 19
  • 42
0

Working code

# importing the required module
import timeit

# code snippet to be executed only once
mysetup = '''
from collections import OrderedDict
def gener():
 some lines of code here
 return x'''

# code snippet whose execution time is to be measured
mycode="gener()"



# timeit statement
nb=10
print("The code run {} time in: ".format(nb ))
print("{} secondes".format(timeit.timeit(setup = mysetup,
                stmt = mycode,
                number = nb)))

print("done")

execution time was almost the same with the one got below

start = time.time()
my code here
end = time.time()
print(end - start)

0.23 sec with timeit and with the basic measurement code above 0.24 ,they both fluctuate... So thanks, question resolved

hughes
  • 177
  • 1
  • 5
  • 11