Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
脚本运行时的php垃圾收集_Php_Performance_Drupal_Garbage Collection - Fatal编程技术网

脚本运行时的php垃圾收集

脚本运行时的php垃圾收集,php,performance,drupal,garbage-collection,Php,Performance,Drupal,Garbage Collection,我有一个在cron上运行的PHP脚本,执行它最多需要15分钟。每隔一段时间,我会让它吐出内存,这样我就能看到发生了什么。第一次它告诉我我的用量是10兆。当剧本完成时,我已经有114兆了 在脚本运行时,PHP是否进行垃圾收集?或者所有的记忆都发生了什么?我能做些什么来强制垃圾收集吗。我的脚本所做的任务是每晚向Drupal导入数千个节点。所以它经常做同样的事情 有什么建议吗?尽可能多地使用unset(),更频繁地检查已用内存。是的,php在运行时在一些条件下进行垃圾收集。 下面是一个关于php.ne

我有一个在cron上运行的PHP脚本,执行它最多需要15分钟。每隔一段时间,我会让它吐出内存,这样我就能看到发生了什么。第一次它告诉我我的用量是10兆。当剧本完成时,我已经有114兆了

在脚本运行时,PHP是否进行垃圾收集?或者所有的记忆都发生了什么?我能做些什么来强制垃圾收集吗。我的脚本所做的任务是每晚向Drupal导入数千个节点。所以它经常做同样的事情

有什么建议吗?

尽可能多地使用
unset()
,更频繁地检查已用内存。是的,php在运行时在一些条件下进行垃圾收集。
下面是一个关于php.net的有用的例子。

如果内存增加了那么多,那么您可能不会释放它。您已创建内存泄漏。如果您不取消设置变量、销毁对象和/或它们超出范围,垃圾收集将帮不上忙

您是否在处理完节点后取消设置加载的节点?我已经编写了运行数小时的PHP脚本,处理了数百万条数据库记录,没有任何问题,并且内存使用在一个非常可接受的范围内上下波动。

PHP主要是一个参考计数器(它确实有一些周期检测功能。)如果您保留仍然可以访问的引用,如果不释放,这些引用将很容易累积

用于释放不再使用的变量。如果您只是覆盖变量(例如,使用null),这将只允许GC减少到该变量所需的空间量,而不会像unset那样多,unset实际上允许销毁引用值

您还应该适当地释放您使用的任何资源等

在运行期间,您仍然会看到内存增加,因为GC可以自由地在其自己的时间间隔释放它,例如当有空闲的cpu周期时,或者当它开始运行时内存不足时。

关键是,只要您不需要全局变量,就立即释放它们

对于局部变量和对象属性,您不需要显式调用unset,因为当函数超出范围或对象被销毁时,这些变量和对象属性将被销毁

PHP为所有变量保留一个引用计数,并在该引用计数变为零时销毁它们(在大多数情况下)。对象有一个内部引用计数,变量本身(对象引用)各有一个引用计数。当所有对象引用都已销毁,因为它们的引用可能已达到0时,对象本身将被销毁。例如:

$a = new stdclass; //$a zval refcount 1, object refcount 1
$b = $a;           //$a/$b zval refcount 2, object refcount 1
//this forces the zval separation because $b isn't part of the reference set:
$c = &$a;          //$a/$c zval refcount 2 (isref), $b 1, object refcount 2
unset($c);         //$a zval refcount 1, $b 1, object refcount 2
unset($a);         //$b refcount 1, object refcount 1
unset($b);         //everything is destroyed

但是考虑下面的场景:

class A {
    public $b;
}
class B {
    public $a;
}

$a = new A;
$b = new B;
$a->b = $b;
$b->a = $a;
unset($a); //cannot destroy object $a because $b still references it
unset($b); //cannot destroy object $b because $a still references it
这些循环引用是PHP5.3垃圾收集器的作用所在。您可以使用显式调用垃圾收集器


另请参见手册中的和。

您写入时无法销毁对象$a,因为$b仍然引用它,但为什么在我写入析构函数类a时,在取消设置$a时执行此析构函数