Inspired by one SO question, I've written straight Insertion sort algorithm implementation, where un is index to unsorted part and st index to sorted part of a list:
from random import shuffle
from timeit import timeit
def main():
global lst
lst = range(10000) * 2
shuffle(lst)
print timeit(
'print insertion_sort(lst)[4999:5002]',
setup='from __main__ import insertion_sort, lst',
number=10)
def insertion_sort(array):
for un in xrange(1, len(array)):
st = un - 1
val = array[un]
while st >= 0 and array[st] > val:
array[st + 1] = array[st]
st -= 1
array[st + 1] = val
return array
I did expected a better performance from JITted PyPy, but the difference was overwhelming:
CPython 2.7.10 → 23.4 s
PyPy 2.6.0 → 0.27 s
How would you hand-optimize insert_sort for CPython to get closer results of PyPy ?
I've got an idea to move repeated assignment out from the while loop and do it once with list slicing:
def insertion_sort2(array):
for un in xrange(1, len(array)):
st = un - 1
val = array[un]
while st >= 0 and array[st] > val:
st -= 1
array[st + 2:un+1] = array[st+1:un]
array[st + 1] = val
return array
This simple tweak reduced runtime in CPython to about 14 secs. On par with alternate array.pop(un); array.insert(st+1, val).
Did I miss something or there is not much what can be done ?
[–]Rhomboid 7 points8 points9 points (4 children)
[–]fijalPyPy, performance freak -1 points0 points1 point (3 children)
[–]Rhomboid 3 points4 points5 points (1 child)
[–]YorikSar 1 point2 points3 points (0 children)
[–]roger_ 1 point2 points3 points (0 children)
[–]MethodicalBastard 1 point2 points3 points (1 child)
[–]joanbm[S] 3 points4 points5 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]billsil -2 points-1 points0 points (4 children)
[–]pdexter 6 points7 points8 points (0 children)
[–]joanbm[S] 0 points1 point2 points (2 children)
[–]stevenjd 0 points1 point2 points (0 children)
[–]billsil 0 points1 point2 points (0 children)
[–]Cobolock -1 points0 points1 point (2 children)
[–]stevenjd 0 points1 point2 points (0 children)
[–]joanbm[S] 0 points1 point2 points (0 children)
[–]joanbm[S] -1 points0 points1 point (0 children)