Skip to content

Instantly share code, notes, and snippets.

@will-ca
Last active March 26, 2020 06:04
Show Gist options
  • Save will-ca/35dc57f07a88de947f31023432158d12 to your computer and use it in GitHub Desktop.
Save will-ca/35dc57f07a88de947f31023432158d12 to your computer and use it in GitHub Desktop.
Quick test of the speed difference between `object` and `PyObject*` for frequently re-created `cdef` attributes.
# cython: language_level=3
import cython, random, array, timeit
test_floats = [*range(10000)]
test_tuples = [(i,) for i in range(10000)]
test_switches = array.array('i', [random.randint(0,1) for i in range(10000)])
class addend_ptrwrapper:
def __cinit__(self, obj, nonzero:cython.bint=True):
self.obj = cython.cast(cython.pointer(PyObject), obj)
self.nonzero = nonzero
def __init__(self, obj, nonzero:cython.bint=True):
if not cython.compiled:
addend_ptrwrapper.__cinit__(self, obj, nonzero=nonzero)
def add_ptrwrapped_floats(seq):
s = 0.0
for i in seq:
if i.nonzero:
s += cython.cast(object, i.obj)
return s
def add_ptrwrapped_tuples(seq):
s = 0
for i in seq:
if i.nonzero:
s += len(cython.cast(object, i.obj))
return s
class addend_objwrapper:
def __cinit__(self, obj, nonzero:cython.bint=True):
self.obj = obj
self.nonzero = nonzero
def __init__(self, obj, nonzero:cython.bint=True):
if not cython.compiled:
addend_objwrapper.__cinit__(self, obj, nonzero=nonzero)
def add_objwrapped_floats(seq):
s = 0.0
for i in seq:
if i.nonzero:
s += i.obj
return s
def add_objwrapped_tuples(seq):
s = 0
for i in seq:
if i.nonzero:
s += len(i.obj)
return s
def get_ptrtest_seq(seq, getseq=True):
outseq = []
i = 0
a = cython.cast(array.array, test_switches)
for obj in seq:
w = addend_ptrwrapper.__new__(addend_ptrwrapper, obj, a.data.as_ints[i])
if getseq:
outseq.append(w)
i += 1
return outseq
def get_objtest_seq(seq, getseq=True):
outseq = []
i = 0
a = cython.cast(array.array, test_switches)
for obj in seq:
w = addend_objwrapper.__new__(addend_objwrapper, obj, a.data.as_ints[i])
if getseq:
outseq.append(w)
i += 1
return outseq
def dotime(code):
return min(timeit.repeat(code, globals=globals(), number=1, repeat=1000))
def timeruns():
print("Wrapping floats with pointers:")
print(dotime('get_ptrtest_seq(test_floats, False)'))
print("Wrapping floats with objects:")
print(dotime('get_objtest_seq(test_floats, False)'))
print()
print("Wrapping tuples with pointers:")
print(dotime('get_ptrtest_seq(test_tuples, False)'))
print("Wrapping tuples with objects:")
print(dotime('get_objtest_seq(test_tuples, False)'))
print()
print("Wrapping and summing floats with pointers:")
print(dotime('add_ptrwrapped_floats(get_ptrtest_seq(test_floats))'))
print("Wrapping and summing floats with objects:")
print(dotime('add_objwrapped_floats(get_objtest_seq(test_floats))'))
print()
print("Wrapping and summing tuple lengths with pointers:")
print(dotime('add_ptrwrapped_tuples(get_ptrtest_seq(test_tuples))'))
print("Wrapping and summing tuple lengths with objects:")
print(dotime('add_objwrapped_tuples(get_objtest_seq(test_tuples))'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment