PHP何时在长时间运行的脚本中运行垃圾收集? [英] When does PHP run garbage collection in long running scripts?

查看:107
本文介绍了PHP何时在长时间运行的脚本中运行垃圾收集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我假设PHP在这种情况下不时收集垃圾,并不会一直打到内存限制。



这似乎不是这种情况。



注释




  • 在PHP 7上运行

  • 长时间运行脚本

  • zend.enable_gc = 1

  • 没有全局变量

解决方案

归结到这一点。您 通过调用 gc_collect_cycles()手动触发垃圾回收。



编写了一堆代码来试图追踪这个问题,并归结为两个脚本:

这一个不会崩溃:

  for($ i = 0; $ i <100; $ i ++){
useMemory();
gc_collect_cycles();
}

而这个崩溃:
$ b $ ($ i = 0; $ i <100; $ i ++){
useMemory(); $

  

$ / code>

以下链接可以比较 Blackfire



当你可以看到,当你不调用 gc_collect_cycles 时,它永远不会发生,并且你达到了内存限制,并且PHP自杀。



PHP甚至没有使用GC本身的机会。这背后的理由在 PHP-DEV邮件列表中讨论,但基本上来了直到遇到内存限制时如何运行 __ destruct 方法(需要内存)的复杂情况。 (也在bug追踪器#60982 )。



内存使用功能:



这是我用来'浪费'内存的代码,它有目的地创建只能被垃圾收集器。请注意,如果没有这些循环,只要对象超出范围,对象将通过引用计数来清除。

  class Big {
私人$数据;
public function __construct($ d = 0){
for($ i = 0; $ i <1024 * 10; $ i ++){
$ this-> $ i = chr( rand(97,122));



$ b函数useMemory(){
$ a = new Big();
$ b = new Big();

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


I am writing a PHP cli program that is a worker process for a queue system.

I assumed that PHP collects garbage from time to time in such a case, and won't constantly hit the memory limit.

This appears to not be the case.

Notes

  • Running on PHP 7
  • Its a long running script
  • zend.enable_gc = 1
  • There are no global variables

解决方案

It comes down to this. You have to trigger garbage collection manually by calling gc_collect_cycles().

I have written a bunch of code to try and track this down and come down to two scripts:

This one doesn't crash:

for($i = 0;$i < 100;$i++) {
    useMemory();
    gc_collect_cycles();
}

And this one crashes:

for($i = 0;$i < 100;$i++) {
    useMemory();
}

Here is a link to compare these scripts on Blackfire

As you can see, when you don't call gc_collect_cycles it never happens, and you get to the memory limit, and PHP kills itself.

PHP doesn't even use this opportunity to GC itself. The reasoning behind this is discussed on the PHP-DEV mailing list, but basically comes down to complications of how to run __destruct methods, that require memory, when the memory limit has been reached. (Also on the bug tracker #60982).

Memory usage func:

This is the code I used to 'waste' memory, it purposefully creates cyclic references that can only be cleaned by the garbage collector. Note that without these cycles the objects will be cleaned by reference counting as soon as they fall out of scope.

class Big {
    private $data;
    public function __construct($d = 0) {
        for($i = 0;$i< 1024 * 10;$i++) {
            $this->$i = chr(rand(97, 122));
        }
    }
}

function useMemory() {
    $a = new Big();
    $b = new Big();

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

这篇关于PHP何时在长时间运行的脚本中运行垃圾收集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆