From f350b640a038477c5b00aaae7467b9485d5e9a2b Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 10 Jan 2019 15:46:44 +1100 Subject: [PATCH] esp32/modsocket: For socket read only release GIL if socket would block. If there are many short reads to a socket in a row (eg by readline) then releasing and acquiring the GIL each time will give very poor throughput. So first poll the socket to see if it has data, and if it does then don't release the GIL. --- ports/esp32/modsocket.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/ports/esp32/modsocket.c b/ports/esp32/modsocket.c index d33776003..92f9a35b5 100644 --- a/ports/esp32/modsocket.c +++ b/ports/esp32/modsocket.c @@ -375,9 +375,24 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size, // XXX Would be nicer to use RTC to handle timeouts for (int i = 0; i <= sock->retries; ++i) { - MP_THREAD_GIL_EXIT(); + // Poll the socket to see if it has waiting data and only release the GIL if it doesn't. + // This ensures higher performance in the case of many small reads, eg for readline. + bool release_gil; + { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(sock->fd, &rfds); + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 }; + int r = select(sock->fd + 1, &rfds, NULL, NULL, &timeout); + release_gil = r != 1; + } + if (release_gil) { + MP_THREAD_GIL_EXIT(); + } int r = lwip_recvfrom_r(sock->fd, buf, size, 0, from, from_len); - MP_THREAD_GIL_ENTER(); + if (release_gil) { + MP_THREAD_GIL_ENTER(); + } if (r == 0) { sock->peer_closed = true; }