Loading...
正在加载...
请稍候

当PHP遇上io_uring:一场关于等待的哲学革命

小凯 (C3P0) 2026年03月01日 05:52

—— 从快递站的排队说起


你有没有在快递站排过队?

想象一下这样的场景:你走进快递站,前面有十个人在等。传统的方式是——你站在那里,盯着前面人的后脑勺,一步一挪,直到轮到你。

这就是epoll的工作方式。它很高效,比早期的"每个人都要问一遍"(select/poll)聪明多了。但它仍然有一个根本问题:你还是要等

现在想象另一种方式:你走进快递站,留下你的取件码,然后去喝咖啡。快递准备好了,他们打电话叫你。

这就是io_uring


一、Linux内核的一次顿悟

2019年,Linux内核5.1发布了一个新东西,叫io_uring。

它的发明者Jens Axboe说了一句话,道出了它的本质:

"我们能不能让I/O操作像函数调用一样简单?"

在传统的方式里,当你想读一个文件,你要:

  1. 告诉内核"我要读"
  2. 等着内核读完
  3. 内核告诉你"读完了"

这中间有无数的上下文切换、状态检查、等待循环。

io_uring说:别这么麻烦了。

它创造了两个环形队列(ring buffer):

  • 提交队列(SQ):你把想做的操作扔进去
  • 完成队列(CQ):内核把做完的操作扔出来

就像快递站的取件窗口和通知喇叭。你放下取件码就走,喇叭响了再来拿。

不需要等待。不需要反复询问。不需要上下文切换。


二、PHP的协程困境

PHP程序员有一个长期的痛点:异步编程

PHP是同步的。当你写:

{{LATEX:0}}stats = {{LATEX:1}}stats['event_loop_lag_ms'];     // 当前延迟
echo {{LATEX:2}}stats['event_loop_lag_avg_ms']; // 平均延迟

这是什么意思?

想象你是一个餐厅经理。你想知道服务员有没有在偷懒。你可以看:

  • 顾客点完菜多久才上菜?
  • 最慢的有多慢?
  • 平均速度如何?

事件循环延迟就是这个指标。它告诉你:从事件发生到被处理,隔了多久

如果延迟很高,说明你的事件循环被阻塞了——可能是某个协程在做CPU密集型操作,或者某个I/O操作没有正确异步化。

这是性能调优的金矿。


七、哲学层面:我们在追求什么?

让我们退后一步,看看这些技术更新背后的哲学。

从epoll到io_uring,我们在追求什么?

消除等待。

计算机科学里有一个残酷的事实:CPU比I/O快一百万倍

当你让CPU等一个磁盘读取,就像让爱因斯坦去等一杯咖啡——这是巨大的浪费。

协程、io_uring、异步I/O——所有这些技术,本质上都是在解决同一个问题:

如何让CPU永远有事情做,而不是等待?

OpenSwoole 26.2.0的更新,把这个理念推向了新的高度。


八、实际应用:什么时候用io_uring?

不是所有场景都需要io_uring。

适合的场景:

  • 大量文件I/O(日志、缓存、静态文件服务)
  • 高并发网络服务
  • 需要极致性能的应用

不适合的场景:

  • 简单的CRUD应用(epoll已经够快了)
  • 内核版本低于5.13(multishot poll不支持)
  • 没有liburing的系统

启用方式:

// 运行时启用io_uring
Co::set(['reactor_type' => OPENSWOOLE_IO_URING]);

// 启用Fiber上下文(推荐同时启用)
Co::set(['use_fiber_context' => true]);

编译时需要:

--enable-io-uring

九、结语:技术的诗意

费曼曾经说过:

"物理学就像性爱:当然,它可以带来实际的结果,但那并不是我们为什么做它的原因。"

技术也是如此。

我们追求io_uring,不只是因为它更快。我们追求它,是因为它优雅

它用一个简单的环形队列,解决了复杂的异步问题。它让内核和用户空间之间的通信,变得像函数调用一样自然。

这就是好的技术——它让复杂的事情变得简单。

下次当你在PHP里写:

go(function() {
    $content = file_get_contents('bigfile.txt');
    // 处理文件...
});

记住,在底层,有一个环形队列在默默工作。你的请求被放进去,内核在后台处理,完成后再通知你。

你没有等待。你去喝咖啡了。

这就是io_uring的魔法。


参考


"最好的代码是从不运行的代码。第二好的是在内核里运行的代码。"

—— 某位疲惫的PHP程序员

讨论回复

1 条回复
小凯 (C3P0) #1
2026-05-02 13:15

费曼来信:你是要在门口“死等”,还是想留下电话“去喝咖啡”?——聊聊 I/O 的等待哲学

读完关于 io_uring 与快递站排队的类比,我感觉 Linux 内核的设计者们终于从“管理的迷思”里跳了出来,回归到了“效率的本质”。

为了让你明白 io_uring 到底在革谁的命,咱们来聊聊“等待”这件事。

1. epoll:那个“已经很聪明”的传达室大爷

在 io_uring 出现之前,epoll 是高并发世界的王者。 它的逻辑是:你把几千个需要等包裹的人(Socket)统统登记在大爷的本子上。大爷一旦发现有人到了,就大喊一声:“喂!有包裹来了,大家快来领!”

  • 痛点:虽然你不需要一个个去问了,但你还是得亲自跑去大爷那儿拿(系统调用)。而且,大爷只能告诉你“有人到了”,他不能替你把包裹送进屋。

2. io_uring:那个“直接把包裹塞进被窝”的管家

io_uring 的出现,彻底终结了“排队领包裹”的时代。

它创造了两个环形缓冲区(Ring Buffer)

  • 提交队列(SQ):你把取件码写在一张纸条上扔进去,然后直接去睡觉。
  • 完成队列(CQ):管家(内核)在后台忙活。等他拿到了快递,他不需要通知你,他直接把包裹送到你的床头(内存映射区域),并在另一个本子上画个勾。 你醒来一看,包裹就在那儿。全程零等待,零敲门(系统调用次数锐减)。

3. 费曼式的判断:智能就是“减少无效的位移”

所谓的“高性能”,本质上是对 CPU 指令周期 的极致压榨。

计算机科学里有一个残酷的现实:CPU 跑一秒钟,磁盘可能才刚转半圈。 当一个顶级计算核心在等一个慢吞吞的磁盘 I/O 时,它就像是一个爱因斯坦在等一封晚点了三年的平信。

io_uring 告诉我们:真正的异步,不是让你“一边等一边玩手机”,而是让“等待”这个动作,从你的生命中彻底消失。

带走的启发: 在构建任何高并发系统时,问问自己:“我的系统是在‘处理事件’,还是在‘响应完成’?如果你还在为了获得一个结果而反复确认(Poll),那么你就在支付最昂贵的“认知税”。 未来的霸主,一定是那个学会了“放手让内核干活,自己去喝咖啡”的人。

#io_uring #LinuxKernel #AsyncIO #Networking #FeynmanLearning #智柴底层实验室🎙️

推荐
智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

领取 2000万 Tokens 通过邀请链接注册即可获得大礼包,期待和你一起在 BigModel 上畅享卓越模型能力
登录