aboutsummaryrefslogtreecommitdiff
path: root/src/unix/linux.c
diff options
context:
space:
mode:
authorAndy Pan <i@andypan.me>2024-07-30 07:59:41 +0800
committerGitHub <noreply@github.com>2024-07-29 19:59:41 -0400
commite5cb1d3d3d4ab3178ac567fb6a7f0f4b5eef3083 (patch)
tree912dc7aa7a8067ccd27a2eba91b98dfa68ffe962 /src/unix/linux.c
parent63b22be08375372c429ec83e7a933a643adfd73c (diff)
downloadlibuv-e5cb1d3d3d4ab3178ac567fb6a7f0f4b5eef3083.tar.gz
libuv-e5cb1d3d3d4ab3178ac567fb6a7f0f4b5eef3083.zip
linux: eliminate a read on eventfd per wakeup (#4400)
Register the eventfd with EPOLLET to enable edge-triggered notification where we're able to eliminate the overhead of reading the eventfd via system call on each wakeup event. When the eventfd counter reaches the maximum value of the unsigned 64-bit, which may not happen for the entire lifetime of the process, we rewind the counter and retry. This optimization saves one system call on each event-loop wakeup, eliminating the overhead of read(2) as well as the extra latency for each epoll wakeup.
Diffstat (limited to 'src/unix/linux.c')
-rw-r--r--src/unix/linux.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/unix/linux.c b/src/unix/linux.c
index ad881867..ad07430e 100644
--- a/src/unix/linux.c
+++ b/src/unix/linux.c
@@ -1385,6 +1385,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents;
e.events = w->pevents;
+ if (w == &loop->async_io_watcher)
+ /* Enable edge-triggered mode on async_io_watcher(eventfd),
+ * so that we're able to eliminate the overhead of reading
+ * the eventfd via system call on each event loop wakeup.
+ */
+ e.events |= EPOLLET;
e.data.fd = w->fd;
fd = w->fd;
@@ -1632,12 +1638,12 @@ int uv_resident_set_memory(size_t* rss) {
long val;
int rc;
int i;
-
+
/* rss: 24th element */
rc = uv__slurp("/proc/self/stat", buf, sizeof(buf));
if (rc < 0)
return rc;
-
+
/* find the last ')' */
s = strrchr(buf, ')');
if (s == NULL)
@@ -2256,7 +2262,7 @@ uint64_t uv_get_available_memory(void) {
}
-static int uv__get_cgroupv2_constrained_cpu(const char* cgroup,
+static int uv__get_cgroupv2_constrained_cpu(const char* cgroup,
uv__cpu_constraint* constraint) {
char path[256];
char buf[1024];
@@ -2267,7 +2273,7 @@ static int uv__get_cgroupv2_constrained_cpu(const char* cgroup,
if (strncmp(cgroup, "0::/", 4) != 0)
return UV_EINVAL;
-
+
/* Trim ending \n by replacing it with a 0 */
cgroup_trimmed = cgroup + sizeof("0::/") - 1; /* Skip the prefix "0::/" */
cgroup_size = (int)strcspn(cgroup_trimmed, "\n"); /* Find the first slash */
@@ -2319,7 +2325,7 @@ static char* uv__cgroup1_find_cpu_controller(const char* cgroup,
return cgroup_cpu;
}
-static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
+static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
uv__cpu_constraint* constraint) {
char path[256];
char buf[1024];
@@ -2337,8 +2343,8 @@ static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
cgroup_size, cgroup_cpu);
if (uv__slurp(path, buf, sizeof(buf)) < 0)
- return UV_EIO;
-
+ return UV_EIO;
+
if (sscanf(buf, "%lld", &constraint->quota_per_period) != 1)
return UV_EINVAL;
@@ -2360,7 +2366,7 @@ static int uv__get_cgroupv1_constrained_cpu(const char* cgroup,
/* Read cpu.shares */
if (uv__slurp(path, buf, sizeof(buf)) < 0)
return UV_EIO;
-
+
if (sscanf(buf, "%u", &shares) != 1)
return UV_EINVAL;