一般来说,PHP 的内存管理对您声明和使用的所有变量都是开箱即用的。使用 refcounting 的概念,PHP 会查看一个变量是否不再使用,然后自动清理它。
垃圾收集器只对对象具有循环引用的情况感兴趣,A 指向 B,B 指向 A。在这种情况下,引用计数不起作用。
如果 PHP 内存中恰好有 10.000 个对象可能是循环的,可能不再使用,那么 PHP 垃圾收集器会在启用时触发,这是默认设置。您可以在运行时使用gc_enable() 和gc_disable() 禁用或启用它。
您也可以调用gc_collect_cycles() 手动清理这些对象。
但是如果需要,如何优化这个过程?运行循环收集器不一定要高效或有用,从 10.000 个潜在对象中,其中许多可能仍在使用中且无法清理。在这种情况下,您正在浪费 CPU 周期来检查所有对象并决定不清理它们。这样做不会减少内存。
通常 GC 只在长时间运行的脚本中触发,有时只有在创建太多对象时才在短的网络请求中触发。一般来说,您不应该考虑太多,因为默认值适用于 99% 的用例。
通过“garbage_stats”PHP 扩展,您可以访问有关 GC 运行的效率和速度以及减少了多少内存的指标和统计信息。它适用于 PHP 7+(因为从那时起钩子才可用):https://github.com/tideways/php_garbage_stats
如果您已安装扩展,则可以通过调用 CLI 脚本查看垃圾收集统计信息:
$ php -dgc_stats.enable=1 -dgc_stats.show_report=1 test.php
Found 7 garbage collection runs in current script.
Collected | Efficency% | Duration | Memory Before | Memory After | Reduction% | Function
----------|------------|----------|---------------|--------------|------------|---------
0 | 0.00 % | 0.01 ms | 365824 | 366320 | -0.14 % | gc_collect_cycles
10000 | 100.00 % | 2.75 ms | 4651320 | 491816 | 89.43 % | foo
10000 | 100.00 % | 3.54 ms | 4652784 | 493280 | 89.40 % | foo
10000 | 100.00 % | 2.11 ms | 4654248 | 494744 | 89.37 % | foo
10000 | 100.00 % | 3.26 ms | 4656168 | 496664 | 89.33 % | Test::foo
9000 | 90.00 % | 1.51 ms | 4694680 | 951176 | 79.74 % | Test::foo
10000 | 100.00 % | 3.11 ms | 5112272 | 952768 | 81.36 % | Test::foo
从网络(例如 Apache 或 FPM)请求中,您可以使用函数 $runs = gc_stats(); 访问此信息并将其写入日志文件。
根据此信息,您可以做出唯一可能优化的决定:根据运行效率在脚本中启用或禁用 GC。