io_uring 凭什么比 epoll 快——从共享环形缓冲区到内核线程池,追踪零拷贝提交的 3 层设计
io_uring 比 epoll 快,不是因为内核里某段代码写得更聪明,而是因为它在架构层面重新设计了用户态和内核态之间的 I/O 边界。这个重新设计分三层,每一层各解决一个 epoll 必须付出的代价:共享环形缓冲区消除提交路径上的系统调用,SQPOLL 内核线程池消除上下文切换的 CPU 开销,Fixed Buffer 预注册消除数据搬运的内存拷贝。
epoll 模型
在拆 io_uring 之前,先把 epoll 的代价摊开看。很多人用了多年 epoll,觉得它已经很好了——确实,从 select/poll 到 epoll 是一次重大进步,但 epoll 有几笔开销是它的架构决定的,无论怎么调优都省不掉。
第一笔:syscall 穿越税
一个典型的 epoll echo server 处理一次请求,最少要走多少次系统调用?
// 主循环里的系统调用序列intn=epoll_wait(epfd,events,<