Friday, March 26, 2010

Python micro-optimization theatre: call dispatch

Python has no switch statement, so if you want to switch control flow based on the value of a variable there are two obvious ways to do it:
if v == 'a':
  ...
elif v == 'b':
  ...
elif v == 'c':
  ...
and
def a():
  ...

def b():
  ...

dispatch = {'a': a,
            'b': b,
            ...
           }

dispatch[v]()
How do these stack up speed-wise? It depends on the access pattern and how many branches you have. If the first branch will usually be taken (v == 'a'), you'll be better off with the first approach. If you usually go down 4 or more branches, dict dispatch is better.
# dict dispatch always takes the same amount of time
In [3]: %timeit f1('g')
1000000 loops, best of 3: 357 ns per loop

###################################

# 7 if statements before we find a match takes longer than
# dict dispatch
In [4]: %timeit f2('g')
1000000 loops, best of 3: 491 ns per loop

# 4 is the same as a dict dispatch
In [7]: %timeit f2('d')
1000000 loops, best of 3: 359 ns per loop

# Taking the first branch is always faster
In [10]: %timeit f2('a')
1000000 loops, best of 3: 215 ns per loop
Code used:
def a():
  pass

def b():
  pass

def c():
  pass

def d():
  pass

def e():
  pass

def f():
  pass

def g():
  pass

dispatch = {'a': a,
            'b': b,
            'c': c,
            'd': d,
            'e': e,
            'f': f,
            'g': g}

def f1(v):
  dispatch[v]()

def f2(v):
  if v == 'a':
    pass
  elif v == 'b':
    pass
  elif v == 'c':
    pass
  elif v == 'd':
    pass
  elif v == 'e':
    pass
  elif v == 'f':
    pass
  elif v == 'g':
    pass

Be the first to reply!

Post a Comment

By submitting a comment you assert that it is your own original work and agree to grant a non-exclusive licence to Brandon Thomson to display it on log.bthomson.com.