Why Epoll is 100x Faster Than Select (I/O Multiplexing)
π― The Questionβ
"How do high-performance servers (NGINX, Redis, Node.js) handle 100,000 concurrent client connections on a single thread? Why is Linux
epollfaster than traditionalselect()andpoll()?"
β‘ 30-Second Elevator Pitchβ
When a single server thread manages 10,000 socket connections, usually only 10 of those sockets have active incoming data at any given millisecond.
- With
select()/poll()( Complexity):- The application must copy an array of all 10,000 socket file descriptors from User Space to Kernel Space on every single poll cycle.
- The kernel iterates through all 10,000 sockets one-by-one to check readiness.
- The application must scan all 10,000 sockets again to find the 10 ready ones.
- With
epoll( Event-Driven):- File descriptors are registered once in a kernel-maintained Red-Black Tree.
- When a network packet arrives, the network card interrupt puts that socket directly into an
epollReady List (Doubly Linked List). epoll_wait()returns only the 10 ready sockets in time.
π§ Under-the-Hood: Linear Polling vs. Kernel Event Callbackβ
π¬ The 3 System Calls of epollβ
epoll_create1(): Creates the epoll kernel context instance.epoll_ctl(): Adds, modifies, or deletes monitored file descriptors in the kernel's Red-Black Tree ( one-time setup).epoll_wait(): Suspends the thread until events occur, returning only the ready file descriptors in time.
π Comparison Matrix: select vs. poll vs. epollβ
| Metric | select() | poll() | epoll() |
|---|---|---|---|
| Time Complexity | β‘ (Proportional to active events) | ||
| Max Descriptor Limit | 1024 (FD_SETSIZE) | Unlimited (Array) | Unlimited (Kernel memory) |
| Kernel Data Copy | Copies entire array every call | Copies entire array every call | β‘ Zero copy (Registered once) |
| Kernel Search Mechanism | Linear loop through all FDs | Linear loop through all FDs | Hardware interrupt callback to Ready List |
| Trigger Modes | Level Triggered only | Level Triggered only | Level Triggered & Edge Triggered |
π‘ What Interviewers Ask Next (Follow-Up Traps)β
-
"What is the difference between Level-Triggered (LT) and Edge-Triggered (ET) in epoll?"
- Answer: Level-Triggered (Default) continuously notifies you as long as unread data remains in the socket buffer. Edge-Triggered (High Performance) notifies you only when new data arrives. In ET mode, the application must read using a non-blocking loop until
EAGAIN/EWOULDBLOCKis returned, otherwise remaining data will stall.
- Answer: Level-Triggered (Default) continuously notifies you as long as unread data remains in the socket buffer. Edge-Triggered (High Performance) notifies you only when new data arrives. In ET mode, the application must read using a non-blocking loop until
-
"What is the equivalent of
epollon macOS/BSD and Windows?"- Answer: macOS/BSD uses
kqueue, which operates on a similar event-driven design. Windows usesIOCP(I/O Completion Ports), which uses an asynchronous completion notification model rather than readiness notification.
- Answer: macOS/BSD uses
Interview Answer: select degrades linearly () because it repeatedly copies and scans the entire list of monitored sockets. epoll operates in time by storing sockets in a kernel red-black tree and using hardware interrupt callbacks to deliver only active, ready file descriptors to the application.
πΊ Video Explanationβ
Never Study in Isolation. Join Binary Dose.
Connect with fellow engineers, clear conceptual doubts, and get 2 visual breakdowns & engineering mental models daily across our community channels.
Discord Community
Start at #welcome-and-rules, say hello in #general-chat, clear doubts, and collaborate with engineers worldwide.