kirr has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/40059?usp=email )
Change subject: trx_toolkit/udp_link,data_if: Optimize socket receive ...................................................................... trx_toolkit/udp_link,data_if: Optimize socket receive As can be seen from http://navytux.spb.ru/~kirr/osmo/fake_trx/pyx-base.html (recv_raw_data) the system is spending almost 2x time in wrapping py-overhead compared to actually doing recv syscall! As fake_trx invokes recv a lot of times it makes sense to cut that overhead. -> Do that: - add C-level UDPLink.recv which invokes recv syscall directly without doing any gil release/acquire and which constructs destination bytearray directly via py CAPI. - invoke that UDPLink via C and also invoke DATAInterface.recv_raw_data also via C because the only users of those functions are in DATAInterface. - we can be sure that returning bytearray instead of bytes is ok because those bytearrays are passed to Msg.parse_msg and it accepts bytearrays just fine. Using bytearrays instead of bytes will be convenient in the follow-up patches. Change-Id: I7e6c10071c31be5947f7c47d0ccbeee90dcb365b --- M src/target/trx_toolkit/data_if.pxd M src/target/trx_toolkit/data_if.pyx M src/target/trx_toolkit/udp_link.pxd M src/target/trx_toolkit/udp_link.pyx A src/target/trx_toolkit/xpy.pxd 5 files changed, 24 insertions(+), 3 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/59/40059/1 diff --git a/src/target/trx_toolkit/data_if.pxd b/src/target/trx_toolkit/data_if.pxd index 03a11c5..564a6cd 100644 --- a/src/target/trx_toolkit/data_if.pxd +++ b/src/target/trx_toolkit/data_if.pxd @@ -4,3 +4,5 @@ cdef class DATAInterface(UDPLink): cdef readonly int _hdr_ver + + cdef recv_raw_data(self) diff --git a/src/target/trx_toolkit/data_if.pyx b/src/target/trx_toolkit/data_if.pyx index 14b8808..d5e4910 100644 --- a/src/target/trx_toolkit/data_if.pyx +++ b/src/target/trx_toolkit/data_if.pyx @@ -56,9 +56,8 @@ msg.ver, self._hdr_ver)) return False - def recv_raw_data(self): - data, _ = self.sock.recvfrom(512) - return data + cdef recv_raw_data(self): + return self.recv(512) def recv_tx_msg(self): # Read raw data from socket diff --git a/src/target/trx_toolkit/udp_link.pxd b/src/target/trx_toolkit/udp_link.pxd index 8698cab..ba145ec 100644 --- a/src/target/trx_toolkit/udp_link.pxd +++ b/src/target/trx_toolkit/udp_link.pxd @@ -18,6 +18,7 @@ cdef sockaddr_in remote_addr cdef _send(self, object data) # bytes|bytearray|str + cdef bytearray recv(self, Py_ssize_t bufsize) cdef _raise_oserr() diff --git a/src/target/trx_toolkit/udp_link.pyx b/src/target/trx_toolkit/udp_link.pyx index c54845b..696f966 100644 --- a/src/target/trx_toolkit/udp_link.pyx +++ b/src/target/trx_toolkit/udp_link.pyx @@ -22,6 +22,7 @@ from cpython cimport PyBytes_AS_STRING, PyBytes_GET_SIZE, PyUnicode_AsUTF8AndSize from cpython.bytearray cimport PyByteArray_FromStringAndSize, PyByteArray_AS_STRING, PyByteArray_GET_SIZE +from xpy cimport PyByteArray_Resize from libc.errno cimport errno from libc.string cimport strerror @@ -33,6 +34,7 @@ cdef extern from "<sys/socket.h>": ssize_t sendto(int fd, const void *buf, size_t len, int flags, const sockaddr *dst_addr, int addrlen) + ssize_t recv(int fd, void *buf, size_t len, int flags) cdef class UDPLink: @@ -95,5 +97,18 @@ self.sock.sendto(data, remote) + cdef bytearray recv(self, Py_ssize_t bufsize): + buf = PyByteArray_FromStringAndSize(NULL, bufsize) + + # NOTE we do not release/reacquire gil to save us from gil ping-pong performance penalty + # we can do that because the socket is non-blocking + n = recv(self.sock_fd, PyByteArray_AS_STRING(buf), bufsize, 0) + if n == -1: + _raise_oserr() + if n != bufsize: + PyByteArray_Resize(buf, n) + return buf + + cdef _raise_oserr(): raise OSError(errno, strerror(errno)) diff --git a/src/target/trx_toolkit/xpy.pxd b/src/target/trx_toolkit/xpy.pxd new file mode 100644 index 0000000..3993dc7 --- /dev/null +++ b/src/target/trx_toolkit/xpy.pxd @@ -0,0 +1,4 @@ +cdef extern from "Python.h": + # PyByteArray_Resize is wrongly declared in cpython.bytearray + # https://github.com/cython/cython/pull/6787 + int PyByteArray_Resize(bytearray buf, Py_ssize_t len) except -1 -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/40059?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I7e6c10071c31be5947f7c47d0ccbeee90dcb365b Gerrit-Change-Number: 40059 Gerrit-PatchSet: 1 Gerrit-Owner: kirr <k...@nexedi.com> Gerrit-CC: fixeria <vyanits...@sysmocom.de> Gerrit-CC: osmith <osm...@sysmocom.de> Gerrit-CC: pespin <pes...@sysmocom.de>