diff --git a/packages/bun-usockets/src/context.c b/packages/bun-usockets/src/context.c index 048f773858..605bb6de11 100644 --- a/packages/bun-usockets/src/context.c +++ b/packages/bun-usockets/src/context.c @@ -130,6 +130,7 @@ void us_internal_socket_context_unlink_socket(int ssl, struct us_socket_context_ next->prev = prev; } } + us_internal_disable_sweep_timer(context->loop); us_socket_context_unref(ssl, context); } void us_internal_socket_context_unlink_connecting_socket(int ssl, struct us_socket_context_t *context, struct us_connecting_socket_t *c) { @@ -147,6 +148,7 @@ void us_internal_socket_context_unlink_connecting_socket(int ssl, struct us_sock next->prev_pending = prev; } } + us_internal_disable_sweep_timer(context->loop); us_socket_context_unref(ssl, context); } @@ -172,6 +174,7 @@ void us_internal_socket_context_link_connecting_socket(int ssl, struct us_socket } context->head_connecting_sockets = c; us_socket_context_ref(ssl, context); + us_internal_enable_sweep_timer(context->loop); } @@ -185,6 +188,7 @@ void us_internal_socket_context_link_socket(struct us_socket_context_t *context, } context->head_sockets = s; us_socket_context_ref(0, context); + us_internal_enable_sweep_timer(context->loop); } struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context) { diff --git a/packages/bun-usockets/src/internal/internal.h b/packages/bun-usockets/src/internal/internal.h index 1989d5d58d..360a676954 100644 --- a/packages/bun-usockets/src/internal/internal.h +++ b/packages/bun-usockets/src/internal/internal.h @@ -116,6 +116,8 @@ extern struct addrinfo_result *Bun__addrinfo_getRequestResult(struct addrinfo_re /* Loop related */ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, int events); void us_internal_timer_sweep(us_loop_r loop); +void us_internal_enable_sweep_timer(struct us_loop_t *loop); +void us_internal_disable_sweep_timer(struct us_loop_t *loop); void us_internal_free_closed_sockets(us_loop_r loop); void us_internal_loop_link(struct us_loop_t *loop, struct us_socket_context_t *context); diff --git a/packages/bun-usockets/src/internal/loop_data.h b/packages/bun-usockets/src/internal/loop_data.h index 3a2186457d..1a950c2372 100644 --- a/packages/bun-usockets/src/internal/loop_data.h +++ b/packages/bun-usockets/src/internal/loop_data.h @@ -35,6 +35,7 @@ typedef void* zig_mutex_t; // IMPORTANT: When changing this, don't forget to update the zig version in uws.zig as well! struct us_internal_loop_data_t { struct us_timer_t *sweep_timer; + int sweep_timer_count; struct us_internal_async *wakeup_async; int last_write_failed; struct us_socket_context_t *head; diff --git a/packages/bun-usockets/src/loop.c b/packages/bun-usockets/src/loop.c index 7830c5ca47..bcbea5a0ef 100644 --- a/packages/bun-usockets/src/loop.c +++ b/packages/bun-usockets/src/loop.c @@ -18,6 +18,7 @@ #include "libusockets.h" #include "internal/internal.h" #include +#include #ifndef WIN32 #include #endif @@ -29,11 +30,28 @@ extern void __attribute((__noreturn__)) Bun__panic(const char* message, size_t l #define BUN_PANIC(message) Bun__panic(message, sizeof(message) - 1) #endif +void sweep_timer_cb(struct us_internal_callback_t *cb); + +void us_internal_enable_sweep_timer(struct us_loop_t *loop) { + if (loop->data.sweep_timer_count == 0) { + us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000); + } + loop->data.sweep_timer_count++; +} + +void us_internal_disable_sweep_timer(struct us_loop_t *loop) { + loop->data.sweep_timer_count--; + if (loop->data.sweep_timer_count == 0) { + us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, 0, 0); + } +} + /* The loop has 2 fallthrough polls */ void us_internal_loop_data_init(struct us_loop_t *loop, void (*wakeup_cb)(struct us_loop_t *loop), void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop)) { // We allocate with calloc, so we only need to initialize the specific fields in use. loop->data.sweep_timer = us_create_timer(loop, 1, 0); + loop->data.sweep_timer_count = 0; loop->data.recv_buf = malloc(LIBUS_RECV_BUFFER_LENGTH + LIBUS_RECV_BUFFER_PADDING * 2); loop->data.send_buf = malloc(LIBUS_SEND_BUFFER_LENGTH); loop->data.pre_cb = pre_cb; @@ -547,9 +565,9 @@ void us_internal_dispatch_ready_poll(struct us_poll_t *p, int error, int eof, in } } -/* Integration only requires the timer to be set up */ +/* Integration only requires the timer to be set up, but not automatically enabled */ void us_loop_integrate(struct us_loop_t *loop) { - us_timer_set(loop->data.sweep_timer, (void (*)(struct us_timer_t *)) sweep_timer_cb, LIBUS_TIMEOUT_GRANULARITY * 1000, LIBUS_TIMEOUT_GRANULARITY * 1000); + /* Timer is now controlled dynamically by socket count, not enabled automatically */ } void *us_loop_ext(struct us_loop_t *loop) { diff --git a/src/deps/uws/InternalLoopData.zig b/src/deps/uws/InternalLoopData.zig index 69918ec02a..e750ce08be 100644 --- a/src/deps/uws/InternalLoopData.zig +++ b/src/deps/uws/InternalLoopData.zig @@ -2,6 +2,7 @@ pub const InternalLoopData = extern struct { pub const us_internal_async = opaque {}; sweep_timer: ?*Timer, + sweep_timer_count: i32, wakeup_async: ?*us_internal_async, last_write_failed: i32, head: ?*SocketContext,