mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 21:32:05 +00:00
## Summary - Switch both eventfd wakeup sites (Zig IO watcher loop and usockets async) to edge-triggered (`EPOLLET`) epoll mode, eliminating unnecessary `read()` syscalls on every event loop wakeup - Add `EAGAIN`/`EINTR` overflow handling in `us_internal_async_wakeup`, matching libuv's approach ([commit `e5cb1d3d`](https://github.com/libuv/libuv/commit/e5cb1d3d)) With edge-triggered mode, each `write()` to the eventfd produces a new edge event regardless of the current counter value, so draining the counter via `read()` is unnecessary. The counter will never overflow in practice (~18 quintillion wakeups), but overflow handling is included defensively. ### Files changed - **`src/io/io.zig`** — Add `EPOLL.ET` to eventfd registration, replace drain `read()` with `continue` - **`packages/bun-usockets/src/eventing/epoll_kqueue.c`** — Set `leave_poll_ready = 1` for async callbacks, upgrade to `EPOLLET` via `EPOLL_CTL_MOD`, add `EAGAIN`/`EINTR` handling in wakeup write ## Test plan - [x] Verified with `strace -f -e trace=read,eventfd2` that eventfd reads are fully eliminated after the change (0 reads on the eventfd fd) - [x] Confirmed remaining 8-byte reads in traces are timerfd reads (legitimate, required) - [x] Stress tested with 50 concurrent async tasks (1000 total `Bun.sleep(1)` iterations) — all completed correctly - [x] `LinuxWaker.wait()` (used by `BundleThread` as a blocking sleep) is intentionally unchanged 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>