From 507f3046d104db2be2c33d5e8fc0d5322818a62c Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 14 Feb 2024 11:20:44 +0100 Subject: [PATCH] linux: create io_uring sqpoll ring lazily (#4315) It's been reported that creating many event loops introduces measurable overhead now that libuv creates an sqpoll-enabled ring. I don't really see any change in CPU time with or without this change but deferring ring creation until it's actually used seems like a good idea, and comes with no downsides that I can think of, so let's do it. Fixes: https://github.com/libuv/libuv/issues/4308 --- src/unix/linux.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/unix/linux.c b/src/unix/linux.c index 4164e90d..0dd11438 100644 --- a/src/unix/linux.c +++ b/src/unix/linux.c @@ -622,7 +622,7 @@ fail: static void uv__iou_delete(struct uv__iou* iou) { - if (iou->ringfd != -1) { + if (iou->ringfd > -1) { munmap(iou->sq, iou->maxlen); munmap(iou->sqe, iou->sqelen); uv__close(iou->ringfd); @@ -636,7 +636,7 @@ int uv__platform_loop_init(uv_loop_t* loop) { lfields = uv__get_internal_fields(loop); lfields->ctl.ringfd = -1; - lfields->iou.ringfd = -1; + lfields->iou.ringfd = -2; /* "uninitialized" */ loop->inotify_watchers = NULL; loop->inotify_fd = -1; @@ -645,7 +645,6 @@ int uv__platform_loop_init(uv_loop_t* loop) { if (loop->backend_fd == -1) return UV__ERR(errno); - uv__iou_init(loop->backend_fd, &lfields->iou, 64, UV__IORING_SETUP_SQPOLL); uv__iou_init(loop->backend_fd, &lfields->ctl, 256, 0); return 0; @@ -764,6 +763,15 @@ static struct uv__io_uring_sqe* uv__iou_get_sqe(struct uv__iou* iou, uint32_t mask; uint32_t slot; + /* Lazily create the ring. State machine: -2 means uninitialized, -1 means + * initialization failed. Anything else is a valid ring file descriptor. + */ + if (iou->ringfd == -2) { + uv__iou_init(loop->backend_fd, iou, 64, UV__IORING_SETUP_SQPOLL); + if (iou->ringfd == -2) + iou->ringfd = -1; /* "failed" */ + } + if (iou->ringfd == -1) return NULL;