Sebastian Raschka
last updated: 05/07/2014



I would be happy to hear your comments and suggestions.
Please feel free to drop me a note via twitter, email, or google+.


Day 1 - One Python Benchmark per Day

String reversing: [::-1] vs. ''.join(reversed())



String-reverse functions


In [1]:
def reverse_join(my_str):
    return ''.join(reversed(my_str))
    
def reverse_slizing(my_str):
    return my_str[::-1]



Verifying that both functions work


In [2]:
test_str = 'abcdefg'

a = reverse_join(test_str)
b = reverse_slizing(test_str)
assert(a == b and a == 'gfedcba')



Timing


In [4]:
import timeit

funcs = ['reverse_join', 'reverse_slizing']

orders_n = [10**n for n in range(1, 7)]
test_strings = (test_str*n for n in orders_n)
times_n = {f:[] for f in funcs}

for st,n in zip(test_strings, orders_n):
    for f in funcs:
        times_n[f].append(min(timeit.Timer('%s(st)' %f, 
                      'from __main__ import %s, st' %f)
                              .repeat(repeat=3, number=1000)))



Setting up the plot


In [10]:
import platform
import multiprocessing


def print_sysinfo():
    
    print('\nPython version:', platform.python_version())
    print('compiler:', platform.python_compiler())
    
    print('\nsystem     :', platform.system())
    print('release    :', platform.release())
    print('machine    :', platform.machine())
    print('processor  :', platform.processor())
    print('interpreter:', platform.architecture()[0])
    print('CPU count  :', multiprocessing.cpu_count())
    print('\n\n')

In [11]:
%matplotlib inline

In [12]:
import matplotlib.pyplot as plt

def plot_timing(funcs):
    
    labels = [('reverse_join', '"".join(reversed(my_str))'), 
          ('reverse_slizing', 'my_str[::-1]')] 

    plt.rcParams.update({'font.size': 12})

    fig = plt.figure(figsize=(10,8))
    for lb in labels:
        plt.plot([len(test_str)*n for n in orders_n], 
             times_n[lb[0]], alpha=0.5, label=lb[1], marker='o', lw=3)
    plt.xlabel('sample size n')
    plt.ylabel('time per computation in milliseconds [ms]')
    plt.legend(loc=2)
    plt.grid()
    plt.xscale('log')
    plt.yscale('log')
    plt.title('Performance of different string reversing methods')
    max_perf = max( j/s for j,s in zip(times_n['reverse_join'],
                                   times_n['reverse_slizing']) )
    min_perf = min( j/s for j,s in zip(times_n['reverse_join'],
                                   times_n['reverse_slizing']) )
    ftext = 'my_str[::-1] is {:.2f}x to {:.2f}x faster than "".join(reversed(my_str))'\
        .format(min_perf, max_perf)
    plt.figtext(.14,.75, ftext, fontsize=11, ha='left')
    plt.show()



Results


In [13]:
print_sysinfo()
plot_timing(funcs)


Python version: 3.4.1
compiler: GCC 4.2.1 (Apple Inc. build 5577)

system     : Darwin
release    : 13.1.0
machine    : x86_64
processor  : i386
interpreter: 64bit
CPU count  : 2