编程 PHP 8.6 的 Io\Poll:用 epoll/kqueue 替掉手写的 stream_select()

2026-09-27 21:02:49

PHP 8.6 的 Io\Poll:用 epoll/kqueue 替掉手写的 stream_select()

PHP 8.6 新增 Io\Poll 命名空间,提供统一的轮询(readiness multiplexing)接口。后端按平台选择:Linux 用 epoll,BSD/macOS 用 kqueue,Solaris 用 event ports,Windows 用 WSAPoll。对应的 RFC 是 Polling API,已在 PHP 8.6 被接受并实现。

为什么替掉 stream_select()

stream_select() 在用户态被到处手写,问题集中在四点:

  • fd 数量受 FD_SETSIZE 限制,通常只有 1024;
  • 每次调用都要重新构造 fd_set;
  • 返回后需要 O(n) 扫描才知道哪些 fd 就绪;
  • 没有跨平台的事件通知模型。

Io\Poll 把这几件事收进引擎:事件循环不再需要依赖 stream_select()。

接口组成

Io\Poll 下的核心类型是 Context、Event、StreamPollHandle,配合非阻塞 socket 使用。

同一版本还新增了 Time\Duration:最终 readonly 类,纳秒精度。它作为超时/时长的共享类型,供新的轮询 API 使用。

谁需要关心

主要动机来自 PHP 内部——信号处理与 FPM 的工作;次要受众才是用户态的事件循环与异步运行时,比如 ReactPHP、Revolt、AMPHP 这一类。

背景是引擎层一直没有并发调度:Fibers(8.1)只提供协作式切换的底层原语,事件循环留给用户态,于是各家框架各搞一套互不兼容的实现。Polling API 被看作未来引擎级调度器(async scheduler ABI,目标 8.7+)的 I/O 基础。

现在的取舍

  • 跨平台的事件通知由引擎统一提供,取代用户在 stream_select() 之上自行分平台适配。
  • 8.6 落地的是轮询这一层;引擎级调度器仍标注为 8.7+ 的目标,尚未到来。
  • Io\Poll 与 Time\Duration 都是 8.6 的新 API,兼容性上只对 8.6+ 有效。
复制全文 生成海报 PHP 8.6 Io\Poll stream_select epoll

推荐文章

程序员茄子在线接单