PHP垃圾收集和内存优化

PHP垃圾收集和内存优化,php,memory,memory-management,benchmarking,Php,Memory,Memory Management,Benchmarking,我正在做一些PHP内存基准测试,我想知道是否有一种方法可以优化垃圾收集器以减少内存消耗(在JAVA等其他语言中也是如此) 我在php.ini中只找到了三个与GC相关的可定制参数:session.GC\u probability、session.GC\u divisior和session.GC\u maxlifest。这只是针对课程,我并没有对此进行基准测试 到目前为止,我知道可能的优化与代码相关,例如避免循环引用,通过调用gc\u collect\u cycles()(感谢本文)强制执行垃圾收集

我正在做一些PHP内存基准测试,我想知道是否有一种方法可以优化垃圾收集器以减少内存消耗(在JAVA等其他语言中也是如此)

我在php.ini中只找到了三个与GC相关的可定制参数:
session.GC\u probability
session.GC\u divisior
session.GC\u maxlifest
。这只是针对课程,我并没有对此进行基准测试

到目前为止,我知道可能的优化与代码相关,例如避免循环引用,通过调用
gc\u collect\u cycles()
(感谢本文)强制执行垃圾收集循环


有人知道PHP内存管理中的配置技巧或良好实践吗?

我在不再需要变量时使用unset()方法清除变量。

据我所知,使用
gc\u collect\u cycles()强制收集是最接近于在时间t时最小化内存使用的方法

GC当然是一个有时间限制的操作,应用程序很少受到严重的内存限制,因此,在整个程序执行过程中提供不必要地触发GC运行的选项是没有意义的。按照这种思路,PHP确实提供了按需打开和关闭循环收集器的功能(
gc_enable()
gc_disable()
),这样您就可以根据时间优化代码(避免gc决定启动的开销)——当然,很容易看出这是多么有用

一般来说,哲学上的PHP避免了诸如内存管理和GC之类的主题,您的基准测试也许应该尊重这一点,以获得更真实的前景

希望这有帮助


(对@GordonM引用微观优化的评论表示赞同。)

一般来说,PHPs内存管理对于您声明和使用的所有变量都是开箱即用的。使用refcounting这个概念,PHP可以查看变量是否不再使用,然后自动清除它

垃圾收集器仅在对象具有循环引用的情况下才有意义,A指向B,B指向A。在这种情况下,引用计数不起作用

如果PHP内存中正好有10.000个对象是潜在循环的,可能不再使用,那么PHP垃圾收集器将在启用时触发,默认情况下是启用的。您可以在运行时使用
gc\u enable()
gc\u disable()
禁用或启用它

您还可以调用
gc\u collect\u cycles()
手动清理这些对象

但是如果需要,如何优化这个过程呢?运行cycle collector不一定是高效或有用的,从10000个潜在对象来看,其中许多对象可能仍在使用中,无法清理。在这种情况下,检查所有对象并决定不清理它们是在浪费CPU周期。如果这样做,内存将不会减少

通常GC只在长时间运行的脚本中触发,只有在短时间的web请求中才会在创建太多对象时触发。一般来说,您不应该考虑太多,因为默认值适用于99%的用例

通过“垃圾统计”PHP扩展,您可以访问有关GC运行效率和速度以及内存减少量的指标和统计数据。它在PHP7+上工作(因为从那时起钩子才可用):

如果已安装扩展,则可以通过调用以下命令来查看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
从web(例如Apache或FPM)请求中,可以使用函数
$runs=gc_stats()
访问此信息并将其写入日志文件


根据这些信息,您可以做出唯一可以优化的决定:根据脚本的运行效率,在脚本中启用或禁用GC。

通过配置指令,您没有什么可以做的,只有以这样一种方式编写代码,以减少内存使用量,这对大多数人来说本身就是一种误解“程序员”在那里:)除非你真的遇到了由于GC问题导致的内存消耗和/或性能问题,否则我真的不会担心,因为这在很大程度上是一个问题。事实是,我正在搜索这种GC微优化。但是,显然PHP垃圾收集器无法优化。我想确定一下。谢谢。