BSD kqueue is a mountain of technical debt (2021)
Overall view of the article and “technical debt” claim
- Many commenters say the piece asserts that kqueue is “technical debt” without actually demonstrating it.
- Several feel the headline is clickbait or overdramatic; the body reads more like a neutral history/comparison than proof of a “mountain of debt.”
- Multiple people argue “technical debt” is misused and has become almost meaningless in this context.
kqueue vs epoll: design, extensibility, and composability
- One side: epoll’s fd-centric model is seen as more composable:
- New kernel objects just expose a file descriptor and automatically work with epoll, poll, select, and future event APIs.
- You can pass fds between processes, read structured event data via read(), close them to free resources, and reuse generic tooling.
- Counterpoint: kqueue’s filter model is also generic:
- Drivers implement filters like EVFILT_READ/WRITE once, and BSDs even layer poll/select on top of kqueue internally.
- New event types can either define new filters or reuse existing ones; no inherent need to grow kqueue itself.
- Non-fd events (proc, timer, signal) are simpler in kqueue than Linux’s proliferation of *fd APIs.
- Some note that Linux needed timerfd, signalfd, etc. specifically to make those things epoll-able, which others call “ugly” or its own form of debt.
Bugs, pitfalls, and “brokenness”
- Linked critiques of epoll highlight:
- Edge-triggered behavior that’s easy to misuse.
- Confusing semantics around file descriptors vs open file descriptions, including events leaking across process boundaries and continuing for fds you no longer hold.
- Others list signalfd and pidfd as messy or non-capability-based, contrasting with BSD process descriptors.
Async vs sync I/O and portability
- Broad agreement that async I/O APIs are fragmented and hard to use portably; runtimes (libuv, language async runtimes) pay the price.
- Debate over sync vs async:
- Some argue synchronous I/O and threads suffice for most workloads and are easier to reason about.
- Others counter that full-duplex protocols and high-concurrency servers push you toward async/event-driven models.
io_uring and “modern reality”
- io_uring is discussed as a newer, ring-buffered, completion-based design:
- Intended to reduce syscall overhead, which matters more on modern hardware and post-Spectre/Meltdown mitigations.
- Seen as powerful but complex and security-prone; some hardened distros reportedly disable it.