禁用垃圾回收

9
如何在运行时间较长的PHP CLI脚本中禁用垃圾回收?我正在处理脚本中变量的取消设置。

@levu:这会禁用收集器,直到进程的最大可用内存被消耗完为止吗? - HyderA
嗯,你为什么需要这个?看起来是很多工作,而且在 PHP >= 5.3 中 gc 处理程序得到了极大的改进... - Wrikken
3
有人可以解释一下为什么对这个问题进行了负投票吗?就问题而言,它是完全合法的...如果不同意别人的投票,也请投赞成票 :) - Wrikken
@Wrikken,我没有将其下降评级 (dv),但我可以想象这是因为它非常类似于“普通参考问题”。(http://blog.stackoverflow.com/2011/02/are-some-questions-too-simple/) - Gordon
3
@Wrikken: 我已经这么做了。我的意图并不是“这是一个无效的问题”(否则我会关闭它),而是“这个问题没有用处”。原因是:a)这个问题就像“我要把自己的脚打破一样” b)在这个问题之前应该是“unset()/GC是如何工作的?”。有人可能会看到这个问题,得出结论认为这是内存敏感应用程序的一种好方法,甚至更糟糕的是,这是某种用例。 - KingCrunch
我遇到的问题是我的脚本可能会睡眠很长时间,有时甚至超过一小时。而当脚本处于睡眠状态时,垃圾回收器会悄悄地清除我的变量。至少我认为是这样。镇上的居民感到害怕,我呼吁SO的好心人来帮助他们应对这种威胁。 - HyderA
4个回答

12

取消设置变量并不会释放内存!它只是从变量中删除对应值的引用。一旦任何值的引用计数为0,垃圾收集器将收集该值并释放其分配的内存。如果完全禁用GC,则会破坏解释器(在最好的情况下):您的内存中将有许多未引用的数据,并且永远不会被清理。这被称为“内存泄漏”。

PHP是否有垃圾回收机制?


那么,为什么会存在那个设置呢? - Meglio
1
嗨@Meglio,当你分配和重新分配许多变量时,例如在循环中,很容易触发GC多次,这将有更大的性能影响。在这种情况下--流行的“你知道你在做什么”情况--暂时禁用gc可能是有意义的。特别是在类似作业的脚本中,你知道它们很快就会结束,你可以消耗内存,一旦进程停止,就可以让OS释放它。 - KingCrunch
感谢@KingCrunch的解释。因此对于长循环,例如在100万次迭代时,如果性能比内存更重要,关闭GC可能是有意义的,在循环开始之前关闭它,循环结束后再打开-是否是这种情况? - Meglio

7
在我的情况下,问题与运行为cliZend Server有关--它经常和随机崩溃。在互联网上,我发现可以禁用'垃圾回收器'来解决这个问题。
要这样做,
在php.ini中:
zend.enable_gc = Off

此外,它可以直接在cli中进行更改。
$ php -d zend.enable_gc=0 your_script.php

1
这对我在php 5.3.x上很有帮助 - 我猜是因为GC在这个版本中运行在beta模式下。 - eithed

2

尝试过了,它只能在5.3及以上版本中使用,但我正在使用5.2.17。 - HyderA
只影响循环引用垃圾回收,不影响“常规”垃圾回收。 - KingCrunch
@King,没有“通用”的垃圾回收器。这是唯一的GC。 - Gordon
那就是错误的。简而言之,圆形GC随PHP5.3一起提供,你真的相信在5.3之前从未有过GC吗?稍微长一点:在PHP中绝对没有办法分配或释放内存。您只能创建或删除对解释器为您分配的值的引用。 - KingCrunch
@Gordon:PHP早在5.3之前就已经有了垃圾回收器。在5.3之前,它是一个简单的基于引用计数的GC,只检查变量的引用数量(不查看循环引用)。它在您明确取消变量后运行,在您离开作用域后运行(以及在脚本终止时)。5.3添加了一个循环引用收集器到这个基本功能中。禁用gc_disable()只会停止循环GC机制的运行。引用计数原语仍然运行...否则unset()和作用域更改将永远不会释放内存... - ircmaxell
@ircmaxell,我从未说过PHP在5.3之前没有垃圾回收机制,你也看到了Artefacto对我的问题的回答。除了引用计数GC之外,没有“通用”的GC。可能gc_disable仅禁用循环,但只有一个GC。没有两个GC。 - Gordon

2
除了改变配置设置zend.enable_gc之外,还可以通过调用gc_enable()gc_disable()来打开或关闭垃圾收集机制。来源:php.net

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接