」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > PHP:用簡單的話解釋垃圾收集器

PHP:用簡單的話解釋垃圾收集器

發佈於2024-12-11
瀏覽:679

垃圾收集器(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();

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

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

再次强调,这并不神奇,因此只有在少数情况下才必须调用 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 跟踪项目,而不会造成混乱或消耗过多空间。

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

$object = new stdClass;
$map = new WeakMap();
$map[$object] = true;
$object->name = 'some name';
print_r($map);// $object is stored in $map

unset($object);

print_r($map);// $object is cleaned and no longer available

✅ 优点

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

❌ 缺点

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

?优化代码

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

包起来

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

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

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

版本聲明 本文轉載於:https://dev.to/spo0q/php-the-garbage-collector-explained-with-simple-words-1b7d?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3