Skip to content

Instantly share code, notes, and snippets.

@pestilence669
Created March 8, 2017 10:53
Show Gist options
  • Save pestilence669/5f8e684370dcc1b8e2e79c81de8181d9 to your computer and use it in GitHub Desktop.
Save pestilence669/5f8e684370dcc1b8e2e79c81de8181d9 to your computer and use it in GitHub Desktop.
Simple Python benchmark rig
#!/usr/bin/env python
# vim: set ts=4 sw=4 et fileencoding=utf-8:
#
# Simple benchmark & testing rig to play with finding the fastest methods when
# searching for the first value in a sequence, determined by a predicate. This
# file uses: lambda x: x / 2 == target
#
from __future__ import print_function
from inspect import getmembers, isfunction
from itertools import ifilter
import sys
import timeit
ITERATIONS = 1000
target, haystack = 669, range(669 * 4)
def test_next_with_a_generator():
'''next(predicate, None)'''
return next((needle for needle in haystack if needle / 2 == target), None)
def test_next_with_an_iterator_filter():
'''next(ifilter(predicate), None)'''
return next(ifilter(lambda needle: needle / 2 == target, haystack), None)
def test_basic_pythonic_loop():
'''for needle in haystack: # ...'''
for needle in haystack:
if needle / 2 == target:
return needle
def test_while_loop_forward():
'''while i < len(haystack):'''
i = 0
while i < len(haystack):
if haystack[i] / 2 == target:
return haystack[i]
i += 1
def test_while_loop_forward_with_cached_len():
'''while i < len(haystack):'''
i = 0
s = len(haystack)
while i < s:
if haystack[i] / 2 == target:
return haystack[i]
i += 1
def test_while_loop_backward():
'''while i >= 0:'''
i = len(haystack) - 1 # go backward to avoid len(), which has a cost
while i >= 0:
if haystack[i] / 2 == target:
return haystack[i]
i -= 1
def test_filter_with_full_traversal():
'''filter(predicate, haystack)[0]'''
return filter(lambda needle: needle / 2 == target, haystack)[0]
###############################################################################
if __name__ == '__main__':
all_funcs = getmembers(sys.modules[__name__], isfunction)
run_funcs = (f for nm, f in sorted(all_funcs) if nm.startswith('test_'))
results = []
for i, f in enumerate(run_funcs):
print('#' * 80)
print('Test #%d (%s) - %s' % (i, f.__name__, f.__doc__))
command = 'assert(%s() / 2 == target)' % f.__name__
setup = 'from __main__ import %s, target' % f.__name__
duration = timeit.timeit(command, setup=setup, number=ITERATIONS)
results.append((duration, f.__name__))
print('Duration: %fs' % duration)
print('#' * 80)
print('SUMMARY:')
print('\tDURATION\tWORSE\tTEST NAME')
min_duration = min(d for d, n in results)
for duration, name in sorted(results):
pct = (duration / min_duration - 1) * 100.0
print('\t%fs\t%f%%\t%s' % (duration, pct, name))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment