0

I have a function implemented as a lambda as well as a if elif ... and compared the execution time :

light = lambda c, v: {'turn on': 1,
                      'turn off': 0,
                      'toggle': (v+1)%2}[c]

def l(c, v):
    if c == 'turn on':
        return 1
    elif c == 'turn off':
        return 0
    elif c == 'toggle':
        return (v+1)%2
    return v

t = Timer(lambda: light('turn on', 0))
print('light: ' + str(t.timeit(number=23163958)))

t = Timer(lambda: l('turn on', 0))
print('l: ' + str(t.timeit(number=23163958)))

The output is:

light: 8.976719211001182
l: 3.9458757909887936

Why is the if statement almost twice as fast? Is it possible to increase the performance even more? I have to execute the function over 23 million times.

According to this I thought the dict lookup would be faster: https://stackoverflow.com/a/15925086/2014080

Community
  • 1
  • 1
amuttsch
  • 1,254
  • 14
  • 24

1 Answers1

1

The problem is that each call of the lambda you instantiate the dictionary again, this takes time. If the dictionary is just being referenced, not created, it runs quicker than the conditionals.

Some simplified code to demonstrate the point.

from timeit import Timer

d = {'turn on': 1, 'turn off': 0}

light = lambda c : d[c]

t = Timer(lambda: light('turn on'))
print('light: ' + str(t.timeit(number=23163958)))

# light: 3.66314601898
chris
  • 4,840
  • 5
  • 35
  • 66
  • Ah, okay that makes sense. But in `d` it is not possible to reference to the `v` I use in `toggle`. So dict might not be the best option here or can I use `v` somehow in your solution as well? – amuttsch Dec 06 '15 at 11:57
  • i couldn't immediately think of a way to include `v`, but there could well be a better approach. – chris Dec 06 '15 at 12:02
  • @amuttsch The larger the dict is the huger the performance difference will be. A two-element dict is probably slower than a simple `if .. else` -- a thousand-element dict is going to be *way* faster than a thousand-element `if .. elif` dropthrough, – zxq9 Dec 06 '15 at 12:03
  • light = {'turn on': lambda x: 1, 'turn off': lambda x: 0, 'toggle': lambda x: (x+1)%2} works as well, even a bit faster than the ìf` statements. Thanks for the explanation, I got the issue with my previous code. – amuttsch Dec 06 '15 at 12:21