aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George2019-01-10 15:46:44 +1100
committerDamien George2019-01-10 15:46:44 +1100
commitf350b640a038477c5b00aaae7467b9485d5e9a2b (patch)
tree587e950d369e0b1840fb1c2e3d9666eb0d650de4
parentefe0569c260677ac480d8958616f046b992ec6d8 (diff)
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.
-rw-r--r--ports/esp32/modsocket.c19
1 files 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;
}