1

I tried a little test:

import timeit

a = "hi"

def f():
    return "hi"

def g():
    return a

timeit.timeit("f()", globals={"f": f}, number=100000000)
# 6.028764325194061
timeit.timeit("g()", globals={"g": g, "a": a}, number=100000000)
# 6.053381357342005

It seems there is no difference between the normal and "cached" version... why? Maybe Python caches immutables defined in modules, functions and classes by default?

EDIT: furthermore there's a strange fact: the code

timeit.timeit("g()", globals={"g": g}, number=100000000)

gives me no error. But I have not passed the variable a to timeit, should not give me an exception?

Marco Sulla
  • 15,299
  • 14
  • 65
  • 100

1 Answers1

0

Measuring performance is always extremely tricky, since many layers are involved, ranging from your application code, your runtime environment, the pthon interpreter thyt you used, your operating system down to the bare metal (like CPU caching). Havve a look at the SO question about loop performance, for example.

If I run the same test on my machine using python 3.7.3, I get the following results:

4.8285931999998866
5.371130099956645

So there is a difference of ~10% in my case. If I run the same test a few more times, I also get the following results:

4.646976499861921
5.513043400060269

Now there is an ~18% difference between the two implementations. I could probably run the same test a few more times and get a difference of <1%, like you had.

In short: measuring performance differences is really hard, do not trust your findings easily.

EDIT: ad "strange fact": I would assume that you don't need to pass a to timeit, since the call g() does not access the passed variable anyway, but the one referenced during the function definition. Verification: The following code does not raise an exception:

a = 'hi'
def t():
    if a == 'a':
        raise Exception()
timeit.timeit("t()", globals={"t": t, "a": "a"}, number=1000000)
soulmerge
  • 73,842
  • 19
  • 118
  • 155