1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
PYTHON setup.py build_ext --inplace
PYTHON test_profile.py
######## setup.py ###########
from distutils.extension import Extension
from distutils.core import setup
from Cython.Build import cythonize
extensions = [
Extension("collatz", ["collatz.pyx"], define_macros=[('CYTHON_TRACE', '1')])
]
setup(
ext_modules = cythonize(extensions)
)
######## test_profile.py ###########
try:
import line_profiler
except ImportError:
print("No line profiler, skipping test.")
import sys
sys.exit(0)
def assert_stats(profile, name):
profile.print_stats()
stats = profile.get_stats()
assert len(stats.timings) > 0, "No profile stats."
for key, timings in stats.timings.items():
if key[-1] == name:
assert len(timings) > 0
break
else:
raise ValueError("No stats for %s." % name)
from collatz import collatz
func = collatz
profile = line_profiler.LineProfiler(func)
profile.runcall(func, 19)
assert_stats(profile, func.__name__)
from collatz import cp_collatz
func = cp_collatz
profile = line_profiler.LineProfiler(func)
profile.runcall(func, 19)
assert_stats(profile, func.__name__)
from collatz import run_generator, cy_generator
func = cy_generator
profile = line_profiler.LineProfiler(func)
profile.runcall(run_generator, 19)
assert_stats(profile, func.__name__)
from collatz import run_coro, cy_coro
func = cy_coro
profile = line_profiler.LineProfiler(func)
profile.runcall(run_coro, 19)
assert_stats(profile, func.__name__)
from collatz import PyClass
obj = PyClass()
func = obj.py_pymethod
profile = line_profiler.LineProfiler(func)
profile.runcall(func)
assert_stats(profile, func.__name__)
from collatz import CClass
obj = CClass()
func = obj.c_pymethod
profile = line_profiler.LineProfiler(func)
profile.runcall(func)
assert_stats(profile, func.__name__)
func = obj.cp_pymethod
profile = line_profiler.LineProfiler(func)
profile.runcall(func, 19)
assert_stats(profile, func.__name__)
######## collatz.pyx ###########
# cython: linetrace=True
cimport cython
@cython.binding(True)
def collatz(n):
while n > 1:
if n % 2 == 0:
n //= 2
else:
n = 3*n+1
@cython.binding(True)
cpdef cp_collatz(n):
while n > 1:
if n % 2 == 0:
n //= 2
else:
n = 3*n+1
@cython.binding(True)
def cy_generator(int n):
x = 1
for i in range(n):
yield x + 2
# waste some time to avoid 0 runtimes (line profiler cannot handle those)
while <object>(i + x) < n + 10:
i += 2
@cython.binding(True)
def run_generator(n):
assert len(list(cy_generator(n))) == n
@cython.binding(True)
async def cy_coro(int n):
while n > 1:
if n % 2 == 0:
n //= 2
else:
n = 3*n+1
x = <object> n # make sure the computation does not get discarded
@cython.binding(True)
def run_coro(n):
coro = cy_coro(n)
try:
coro.send(None)
except StopIteration:
assert True
else:
assert False, "Coroutine did not raise"
@cython.binding(True)
class PyClass(object):
def py_pymethod(self):
x = 1
for i in range(10):
a = x + 2
return a * 3
@cython.binding(True)
cdef class CClass:
def c_pymethod(self, c=2):
for i in range(10):
a = c + 1
y = self.cmethod(c + a)
return y * 4
cpdef cp_pymethod(self, r):
for i in range(10):
a = r + 1
z = self.c_pymethod(a) + self.cmethod(r)
return z * 2
cdef cmethod(self, s):
for i in range(10):
p = s + 3
return p * 5
|