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 的贡献。

相关推荐
csdn_life184 分钟前
# Debian 10 升级到 Debian 13 指南
运维·debian·php
jiang_changsheng44 分钟前
VMware 虚拟机无法上网排查解决教程
开发语言·网络·php
m0_738120721 小时前
网络安全编程——PHP基础Session详细讲解
android·网络·windows·安全·web安全·php
阿成学长_Cain1 小时前
Windows IP 配置查看器 ipconfig 详解
开发语言·php
拍客圈1 小时前
在 Discuz! 后台设置 SEO 参数(如标题、关键词、描述)后无法保存
服务器·数据库·php
l14372332672 小时前
短剧多语种翻译的技术难点:为什么AI翻译比人工翻译更适合出海?
开发语言·人工智能·php
zhouping@11 小时前
[羊城杯2020]easyphp
web安全·php
亚历山大海12 小时前
AiPPT接口文件PHP版本全,智能生成PPT文件并下载
开发语言·ai·php
电商API_1800790524712 小时前
企业级应用:京东商品详情 API 的高可用架构与多级缓存设计
开发语言·人工智能·python·数据分析·网络爬虫·php
Reuuse12 小时前
【网络基础概念】
开发语言·网络·php