PHP 8.6.0 RC3 撤回三处「更快」改动:hrtime() 快了 4%、fiber 里警告被静音
PHP 8.6.0 RC3 于 2026 年 10 月 8 日发布。RC1 被跳过,所以这是第二个 RC。GA 计划在 2026 年 11 月 19 日,时间表是 RC4 10 月 22 日、RC5 11 月 5 日、GA 11 月 19 日。
RC3 只带 bug 修复,以及若干对 8.6 自身引入的回归的回滚。最大的一处,是 fiber 内部抛出的所有警告都被静音了。
RC3 的内容:
- 没有
php.ini设置时,fiber 不再以error_reporting = 0启动 hrtime()回到CLOCK_MONOTONIC——之前切到 raw clock 后,它在部分机器上跑快了strict_types=1文件里,array_map()的加速编译路径关闭- OPcache 不再把
$cond ? -0.0 : 0.0折叠成单个-0.0 - 内置 web server 不再在每次
HEAD请求时泄漏一个文件描述符 - 一长串 PDO、OpenSSL、Intl 和内存安全修复
hrtime()
PHP 8.6 曾把 POSIX 高精度计时器切到 CLOCK_MONOTONIC_RAW(GH-19221),目的是把 NTP 调整挡在 hrtime() 测量之外。NTP 从不校正 raw clock,所以它按硬件实际频率走。Nicolas Grekas 在 WSL2 下测了一次一秒 sleep:
| 版本 | microtime() | hrtime() |
| 8.5 | 1.000083 s | 1.000086 s |
| 8.6 修复前 | 1.000072 s | 1.038898 s |
| 8.6 RC3 | 1.000158 s | 1.000163 s |
即 hrtime() 快了约 4%。他还指出,内核从 Linux 5.3 起才通过 vDSO 提供 CLOCK_MONOTONIC_RAW,所以在 RHEL 8 这类更老的系统上,每次调用都要付一次系统调用。RC3 回到 CLOCK_MONOTONIC,与 8.5 一致。如果你在 beta 阶段用 hrtime() 做过任何基准测试,需要重跑。PR:GH-23790。
array_map() 与 strict_types
PHP 8.6 会把部分 array_map() 调用编译成另一种形式来提速。在 strict_types=1 文件里,这条新路径会对回调参数做类型检查,而 array_map() 以前从不这么做:
declare(strict_types=1);
array_map(trim(...), [1]);
// 8.5: 正常运行
// 8.6 RC2: TypeError: trim(): Argument #1 ($string) must be of type string, int given
Tim Düsterhus 对 strict_types=1 文件关闭了加速路径,这段代码的行为回到 8.5。Arnaud Le Blanc 另外修复了回调函数名或参数不是字面量时的调用。
OPcache 下的负零
开启 OPcache 时,优化器把 $cond ? -0.0 : 0.0 变成单纯的 -0.0,条件被丢掉。依赖零的符号的代码——比如用 1.0 / $zero 得到 INF 或 -INF——在 OPcache 开启和关闭时会给出不同结果。这种 bug 很难被发现,因为开发环境常常不开 OPcache,而生产环境几乎总是开着。
其他修复
内置 web server 在对静态文件的每次 HEAD 请求中泄漏一个文件描述符(GH-23764)。报告者发现,一个每 40 秒请求一次 php -S 的监控探针,大约 11 小时就会把描述符耗尽。这个 bug 可以追溯到 PHP 8.2。RC3 还修复了客户端在服务端 accept 之前重置连接导致的崩溃,以及 socket 部分写入后错误页面被截断的问题。
Ilia Alshanetsky 承担了其中很大一部分修复,包括一连串 PDO 修复:PDOStatement::execute() 执行失败后不再留下上一次的结果;setFetchMode() 的改动一次性生效;绑定参数的 __toString() 引起的 use-after-free 已消除。PDO_DBLIB 现在会上报 beginTransaction()、commit()、rollBack() 和 lastInsertId() 的错误,而不是把它们吞掉。
升级注意
openssl_sign() 的 RSA-PSS 签名现在使用 OpenSSL 的默认 salt 长度,而不是最大长度。如果你用期望特定 salt 长度的代码去验证这些签名,需要针对 RC3 测试。
UPGRADING 还列出了八月弃用投票通过的三项弃用:用 let 或 is 作为类、函数或常量的名字,以及用 _ 作为常量名或 use 别名。这些不是 RC3 新增的,RC2 已经开始发出 notice。
团队请求不要在 production 环境运行 RC3。