PHP 8.5 垃圾回收改进

PHP 8.5 垃圾回收改进

PHP 内存消耗的大幅优化已经很罕见了。近年来的内存改进范围较小,主要集中在某些类型变量的细节上。

比如改进垃圾回收器(GC)在边缘情况下的表现。Iljia Tovilo 为 PHP 8.5 贡献了这个优化,标题是"将枚举和静态伪闭包标记为不可回收"。

简单来说,对于这两种变量类型,循环回收器不会尝试"收集"它们,大量使用这些实例时就能避免不必要的 GC 运行。

这没有任何副作用,因为这些类型本身不可能形成循环引用,本来就不在 GC 的管辖范围内。

原文链接 PHP 8.5 垃圾回收改进

快速回顾:PHP 的垃圾回收器是如何工作的?

要理解为什么这很有用,先快速回顾一下 PHP 垃圾回收的工作原理。

简单来说,PHP 的 GC 不是持续运行的,而是由阈值触发。这个阈值是:内存中至少有 10,000 个可能存在循环引用的对象或数组。如果这些实例数量不断增加而无法清理,GC 可能会在越来越多的对象上运行,消耗宝贵的计算资源。

因此,减少符合垃圾回收条件的对象数量可以降低 GC 运行的概率,从而提升性能。

PHP 7.3 添加了一个实用函数 gc_status()文档),可以很方便地了解垃圾回收的性能情况。

实际收益是什么?

看一下 PR 中的例子,大量 first class callable 实例被添加到数组中,然后进行迭代。

php 复制代码
<?php

function foo() {}

$array = [];
for ($i = 0; $i < 10_000_000; $i++) {
    $array[] = foo(...);
}

//
// 这个循环是为了确保触发循环回收器:
// - `as $foo` 会增加数组元素的引用计数
// - 变量超出作用域后引用计数又会减少
//
foreach ($array as $foo) {}

echo json_encode(gc_status(), JSON_PRETTY_PRINT);

在旧版 PHP 中,这会触发循环回收器检查所有这些实例是否存在循环引用。由于这些实例不可能有循环引用,这些检查是多余的。对于 1000 万个条目,这导致了 44 次 GC 运行,而 PHP 8.5 及以后版本在相同代码下是 0 次。

定义:"静态伪闭包"

PR 标题说优化适用于"枚举和静态伪闭包"。静态伪闭包显然是更常见的情况,而且术语与用户层面的命名不一致,我们来深入了解一下:什么是"静态伪闭包"?

上面的例子使用了"静态伪闭包",在用户层面通常称为"first-class callable"。在这个例子中,就是 foo(...)

要判断一个 callable 是否是"伪闭包",可以检查该 callable 的反射类的 anonymous 标志是否返回 false,即 (new \ReflectionFunction($callable))->isAnonymous();

类型中的"静态"部分指的是 OOP 中的 static:没有访问对象实例(即 $this)的权限。

在下面这个不同闭包的列表中,你可以看到哪些被 PR 认为是静态伪闭包,哪些不是:

php 复制代码
<?php

class Foo 
{
    public static function bar(): void {}
    public function baz(): void {}    
}

function bar(): void {}

//
// 静态伪闭包
//
var_dump(...);
bar(...);
Foo::bar(...);
$callable = Closure::fromCallable('bar');
$callable(...);

// 伪闭包,但非静态
(new Foo())->baz(...);
// 匿名函数,不是伪闭包
$anon = static function () {};
$anon(...);

枚举的情况

第二种被优化的类型是枚举实例。这在实际项目中的影响可能较小,因为只有当代码库包含大量枚举且每个枚举有很多 case 时才会影响性能。枚举实例是单例的,每个枚举 case 只会被实例化一次。即使有数千个引用指向相同的三四个枚举 case,也不会有影响,因为每个枚举 case 在 GC 的根缓冲区中只能出现一次。

总结

这样的小改进表明,PHP 的内存管理在已经相当成熟的情况下仍然可以继续优化。

这个改动可能在某些情况下提升性能,但更重要的是,它确保垃圾回收运行不会在无关的检查上浪费时间。

感谢 Iljia Tovilo 的贡献。

相关推荐
门思科技12 分钟前
LoRaWAN 设备类别:Class A、B、C 对比与选型指南
c语言·开发语言·php
甲骨文数据库11 小时前
caddy配合PHP(http模式)
php
啊阿狸不会拉杆11 小时前
《计算机网络-自顶向下方法》1.7 计算机网络和因特网的历史 读书笔记
计算机网络·php·perl
智塑未来14 小时前
常用的在线ping测试工具有哪些
服务器·开发语言·php
啊阿狸不会拉杆14 小时前
《计算机网络-自顶向下方法》1.3 网络核心 读书笔记
网络·人工智能·计算机网络·ai·php
171320330计算机毕设编程15 小时前
2027计算机毕设五大方向对比&选题推荐
java·ide·python·算法·django·php·推荐算法
IT小白杨16 小时前
TikTok小店防封号浏览器实战:2026年多店铺环境隔离与账号安全运营技术解析
开发语言·数据库·安全·php·chrome devtools·指纹浏览器
catchadmin17 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.4.0 发布,新增短信服务能力
开发语言·php
Tanshu_API君17 小时前
身份证实名认证接口对接:PHP 接入二要素核验实战
php·api·实名认证·身份证实名认证·身份认证接口·运营商接口·运营商二要素
啊阿狸不会拉杆18 小时前
《计算机网络-自顶向下方法》1.5 协议层次及其服务模型 读书笔记
开发语言·计算机网络·php