首页 >后端开发 >php教程 >PHP:用简单的话解释垃圾收集器

PHP:用简单的话解释垃圾收集器

Linda Hamilton
Linda Hamilton原创
2024-11-29 00:46:11895浏览

垃圾收集器(GC)是 PHP 中的内部内存管理系统,但有一些微妙之处需要理解。

?为什么 GC 会存在?

GC 自动化内存管理,消除了通过手动任务处理内存的麻烦(这会很乏味)。

这使得开发人员可以专注于他们的业务逻辑,而不必过度担心“内存不足”错误。

当然,这不是魔法。

?简而言之 10,000 个对象

释放不再需要的对象可以防止内存泄漏

GC 使用计数机制来确定要丢弃的元素。如果没有引用指向特定对象(即 $counter = 0),则该对象有资格进行清理。

它工作得很好,但一些引用可能有问题:

class A {
    public $b;
}

class B {
    public $a;
}

$a = new A();
$b = new B();

$a->b = $b;
$b->a = $a;

unset($a);
unset($b);

在这种设计不佳的情况下,即使我们取消设置 $a 和 $b,PHP 也不会释放内存,因为它们相互引用,导致 PHP 认为它们仍在使用中。

幸运的是,还有另一种称为循环收集器的机制:

gc_collect_cycles();

粗略地说,收集器会遍历所有引用并应用一种算法来标记正在使用的对象,从而显示要收集的对象(未标记的对象)。

但是,PHP 不会触发自动循环收集,直到达到具有潜在循环引用的 10,000 个对象 的阈值。

再次强调,这不是魔法,因此只有在少数情况下才必须调用 gc_collect_cycles()。

?坦斯塔足球俱乐部

糟糕的设计可能会导致对象之间的关系过于复杂,从而导致更多的引用和更频繁的垃圾回收。

每个引用计数对象都需要额外的存储空间来存储其引用计数。

来源:维基百科 - 引用计数

与内存清理操作相关的开销会显着影响全局性能,并最终增加特定场景中的执行时间。

10 年前,Composer 仅通过使用 gc_disable() 函数就获得了巨大的性能提升。

来源:Composer - 禁用 GC

确实,PHP 7 极大地改进了 GC,所以现在已经不是 2014 年的样子了。

此外,PHP 8 版本改进了内存分配策略,并添加了更多有关 GC 操作的有用统计信息,以便更好地监控(8.3 中的 gc_status())。

大多数PHP应用程序都是请求驱动的,请求结束时内存会自动清除。

再说一遍,这很酷,但并不神奇。异步请求和长期存在的对象/守护进程会发生什么?

您可能会在某些时候遇到内存泄漏。

? PHP 的 GC 有何不同?

此时,你可能还看不出 PHP 的 GC 与其他语言有何不同。

大多数时候,其他语言不依赖引用计数来收集垃圾,或者可能使用不同的实现。

例如,许多使用跟踪算法,该算法也标记未使用的对象,但不会增量操作。这是一个图的遍历。

此外,某些语言不允许这种直接控制(例如,运行时开/关)。

像往常一样,有一些优点和不方便,所以你可能会看到一些混合方法。

?‍?与 PHP 的 GC 交互

您可以利用内置的 gc_* 帮助程序。

例如:

  • gc_collect_cycles 手动触发垃圾收集
  • gc_status() 给出当前状态
  • gc_disable() 禁用它
  • gc_enable() 启用它

这些函数有助于调试或微调垃圾收集必要时

?了解内存错误

您可以阅读这篇文章以获取更多见解:

PHP: The Garbage Collector explained with simple words

PHP:内存错误

spO0q ? ・ 2023 年 5 月 24 日

#php #初学者 #编程

?弱地图可以拯救吗?

PHP 7.4 引入了弱引用,PHP 8 引入了弱映射。

弱映射可以被描述为弱引用的集合。

此数据结构是一种多功能键值存储,可帮助 PHP 跟踪项目,而不会造成混乱或消耗过多空间。

您可能会将其视为临时存储,当不再需要时将立即清除,因为没有[强]引用可以阻止垃圾收集:

class A {
    public $b;
}

class B {
    public $a;
}

$a = new A();
$b = new B();

$a->b = $b;
$b->a = $a;

unset($a);
unset($b);

✅ 优点

  • 非常简单
  • 非常适合缓存或记忆(例如,昂贵的计算)

❌ 缺点

  • 虽然键(对象)不会阻止垃圾回收,但值可以,因此术语“任意值”可能会产生误导(仅使用简单数据类型作为值)
  • 有价值的用例是有限的

?优化代码

  • 利用减少相互依赖性的设计模式
  • 使用依赖注入
  • 不要将太大的数据集加载到内存中,并使用集合和生成器而不是巨大的数组
  • 监控内存使用情况
  • 使用指标分析您的代码
  • 谨慎使用 gc_enable()、gc_disable() 和 gc_collect_cycles()

包起来

对于大多数用法,您不必担心内存管理,因为 PHP 已经处理了它。

但是,由于现代堆栈使用长寿命对象,因此您需要监视应用程序是否存在潜在的内存泄漏。

如果遇到问题,您可能需要优化代码和/或直接与 GC 交互。

以上是PHP:用简单的话解释垃圾收集器的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn