Andrew Svetlov
http://asvetlov.blogspot.com
andrew.svetlov@gmail.com
http://asvetlov.github.io/optimization-moscow-2016/
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("helloworld.pyx")
)
import pyximport
pyximport.install()
import helloworld
native_byteorder = sys.byteorder
def _websocket_mask_python(mask, data):
assert isinstance(data, bytearray), data
assert len(mask) == 4, mask
datalen = len(data)
if datalen == 0:
return bytearray()
data = int.from_bytes(data, native_byteorder)
mask = int.from_bytes(mask * (datalen // 4) + mask[: datalen % 4],
native_byteorder)
return (data ^ mask).to_bytes(datalen, native_byteorder)
$ cython -a module.pyx
$ xdg-open module.html
from cpython cimport PyBytes_AsString
from libc.stdint cimport uint32_t, uint64_t, uintmax_t
cdef extern from "Python.h":
char* PyByteArray_AsString(bytearray ba) except NULL
def _websocket_mask_cython(bytes mask, bytearray data):
cdef:
Py_ssize_t data_len, i
unsigned char * in_buf
const unsigned char * mask_buf
uint32_t uint32_msk
uint64_t uint64_msk
assert len(mask) == 4
data_len = len(data)
in_buf = <unsigned char*>PyByteArray_AsString(data)
mask_buf = <const unsigned char*>PyBytes_AsString(mask)
uint32_msk = (<uint32_t*>mask_buf)[0]
while data_len >= 4:
(<uint32_t*>in_buf)[0] ^= uint32_msk
in_buf += 4
data_len -= 4
for i in range(0, data_len):
in_buf[i] ^= mask_buf[i]
return data
if sizeof(size_t) >= 8:
uint64_msk = uint32_msk
uint64_msk = (uint64_msk << 32) | uint32_msk
while data_len >= 8:
(<uint64_t*>in_buf)[0] ^= uint64_msk
in_buf += 8
data_len -= 8
$ cython -a module.pyx
$ xdg-open module.html
def _websocket_mask_python(mask, data):
...
if bool(os.environ.get('AIOHTTP_NO_EXTENSIONS')):
websocket_mask = _websocket_mask_python
else:
try:
from ._websocket import _websocket_mask_cython
websocket_mask = _websocket_mask_cython
except ImportError: # pragma: no cover
websocket_mask = _websocket_mask_python
class WSTestMixin:
mask = None
def test_a(self):
self.assertEqual(self.mask(..., ...), ...)
class TestCython(WSTestMixin, unittest.TestCase):
mask = _websocket_mask_cython
class TestCython(WSTestMixin, unittest.TestCase):
mask = _websocket_mask_python
Andrew Svetlov
http://asvetlov.blogspot.com
andrew.svetlov@gmail.com
http://asvetlov.github.io/optimization-moscow-2016/