PHP 8.5 在性能、调试和运维方面的新特性

PHP 8.5 在性能、调试和运维方面的新特性

2025 年即将结束,这意味着 PHP 的新版本也已经发布了!

在本文中,我们将重点介绍那些你在上述文章中找不到的,关于 PHP 8.5 在性能、调试和运维方面的变化。

其中一些改动甚至是由 Tideways 的员工直接贡献的。

你是不是最好奇 PHP 8.5 是否比旧版本性能更强?可以看看基准测试
原文链接 PHP 8.5 在性能、调试和运维方面的新特性

性能 (Performance)

针对 === [] 的 OPCode 特殊优化

PHP 编译器可以优化 opcode 以便更高效地运行。在 8.5 版本中,我的同事 Tim 针对 $array === [] 的检查添加了一项优化。在此之前,与 !$arraycount($array) === 0empty($array) 相比,这种检查空数组的方式是最慢的。

在 PHP 8.5 中,这变成了检查空数组最快的方式。

那你现在应该把所有代码都改一遍吗?不。 但这表明,当你对代码进行"微优化"时,随着引擎的演进,你可能会在下一个 PHP 版本中失去这种优势,甚至完全不同的代码路径会变得更快。也许最好的做法是:写你觉得最可读的代码,把性能提升押注在未来引擎的改进上。

优化 match (true)

PHP 8.5 做的另一个编译时优化 是减少 match (true) 语句生成的 opcode 数量。

对于像下面这样的人造代码示例,这带来了 17% (+/- 6%) 的性能提升:

php 复制代码
<?php
function foo($text) {
    $result = match (true) {
        !!preg_match('/Welcome/', $text), !!preg_match('/Hello/', $text) => 'en',
        !!preg_match('/Bienvenue/', $text), !!preg_match('/Bonjour/', $text) => 'fr',
        default => 'other',
    };
    return $result;
}

$i = 1_000_000;
$text = 'Bienvenue chez nous';
while($i--) {
    foo($text);
}

用于 DNS、连接和 SSL 握手重用的持久化 cURL 句柄

PHP 的"无共享(Shared Nothing)"架构在避免内存泄漏和用户间数据意外泄露方面非常有帮助。但当你在每个请求中反复执行相同工作时,它也有其弊端。

例如:cURL HTTP 请求中的 DNS 解析、连接建立和 SSL 握手时间。

在 PHP 8.5 中,你可以通过一个新函数 curl_share_init_persistent,在不同 PHP 请求发起的 HTTP 调用之间共享 DNS、连接和 SSL 握手信息,从而显著减少这些时间

当你在 Web 服务器上多次运行以下 PHP 8.5 代码时,通过观察 cURL 计时器,你会发现第二次调用的速度快了很多,以及具体快了多少:

php 复制代码
<?php
$sh = curl_share_init_persistent([CURL_LOCK_DATA_CONNECT, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_DATA_DNS]);
$ch = curl_init("https://tideways.com");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SHARE, $sh);
curl_exec($ch);

foreach (curl_getinfo($ch) as $k => $v) {
    if (str_ends_with($k, '_time')) {
        echo sprintf("%20s", $k) . "\t" . $v . PHP_EOL;
    }
}

这项变更由 Eric Norris 通过 Add persistent curl share handlesPersistent curl share handle improvement RFCs 贡献。

提升实例化异常和错误的性能

通常来说,PHP 应用程序中不应频繁发生异常,但在某些情况下,它们可能是意外发生的,也可能是完全有意为之。得益于 Niels Dossche 的这个 PR,异常实例化的速度略微变快了。它将一些检查移动到了 PHP 的调试构建(debug builds)中,并在生产构建中跳过这些检查。

改进函数性能

以下核心函数在 PHP 8.5 中获得了性能优化:array_find()array_filter()array_reduce()usort() / uasort()str_pad()implode()pack() 以及 ReflectionProperty::getValue() 及其变体。

运维 (Operations)

OPcache 现在是必选扩展

在 PHP 8.5 中,OPcache 现在是一个必选扩展 ,会自动内置到每个 PHP 二进制文件中。这感谢 Tim、Arnaud 和 Ilija 提交的 RFC。以后不再有"不带 OPcache 运行 PHP"的选项,也不会再发生因意外忘记安装它而导致的问题------这曾是使用 php 官方 Docker 镜像时常见的痛点。

其目标是简化维护,允许以更简单的方式利用 OPcache 的优化器部分,并将代码共享/移动到引擎中。

不过,你仍然可以通过 php.ini 设置来禁用 OPcache。

OPcache 文件缓存只读支持

在 PHP 8.5 之前,你无法将 OPcache 的文件缓存与只读文件系统结合使用。这使得在部署和运行步骤分离的容器环境中(例如在 AWS Lambda 上运行 Bref),无法利用文件缓存。在这些场景中,冷启动时间是重点优化的对象。

Samuel 的这个 PR 添加了一个新的 INI 选项 opcache.file_cache_read_only。设置该选项后,OPcache 不再废弃文件,也不会运行任何会修改文件系统的代码。

该 PR 提到,为了获得最佳效果,应结合设置 opcache.validate_timestamps=0opcache.enable_file_override=1opcache.file_cache_consistency_checks=0

PR 中还包含了 Bref 作者 Matthieu Napoli 的一手经验,他提到在一个测试应用中,这让 AWS Lambda 的冷启动时间减少了 100ms

新的 max_memory_limit INI 指令

在 PHP 8.5 之前,你可以通过调用 ini_set("memory_limit") 且没有任何防护措施地将内存限制修改为不健康的高数值。现在,可以通过配置系统级 INI 设置 max_memory_limit 来防止这种情况,它定义了运行时内存限制可以设置的上限。这一变更由 Frederik Pytlick 在此 PR 中贡献。

新增 PHP_BUILD_PROVIDER 常量

这是另一个对通用应用程序很有帮助的小改动。此前,编译 PHP 时已经可以使用 PHP_BUILD_PROVIDER 环境变量标志来提供关于"谁构建了这个版本"的信息。这些信息会显示在 phpinfo()php -v 的输出中。

通过新的 PHP 常量 PHP_BUILD_PROVIDER,你现在也可以在运行时访问此信息。

很多人已经在 Homebrew、Debian、Docker 和 Fedora 的上游 PHP 构建中使用了这个功能。

调试 (Debugging)

php --ini=diff

通过命令行上的这个新选项,你现在可以查看所有与默认值不同的 INI 变量列表。这对于调试和报告你的 PHP 安装环境 Bug 非常有帮助。

增加运行时启用的堆调试能力

得益于 Arnaud 的这个 PR,PHP 8.5 获得了内存调试能力,而无需 使用像 ASAN/MSAN/Valgrind 这样的专用工具重新编译------这些工具在生产环境中很难获得。现在通过设置环境变量 ZEND_MM_DEBUG,你可以启用不同的内存调试功能。

错误回溯 (Error Backtraces)

得益于 Eric Norris 的 RFC,PHP 输出的致命错误(Fatal Errors)现在默认会显示回溯信息(backtrace)。在此之前,致命错误只会显示错误消息。

新函数:get_exception_handler()get_error_handler()

通过 Arnaud 的这个 RFC,PHP 8.5 增加了两个新函数:get_exception_handlerget_error_handler,它们允许你访问当前的异常或错误处理程序的 callable 对象。

相关推荐
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo3 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack4 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082855 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5