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 <kirr(a)nexedi.com>
Gerrit-CC: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-CC: osmith <osmith(a)sysmocom.de>
Gerrit-CC: pespin <pespin(a)sysmocom.de>