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>

Reply via email to