PHP脚本内存限制和内存优化

时间:2013-03-23 11:51:50

标签: php

我有一个PHP脚本来废弃网站(仅限文本文件)。运行几个小时后,我注意到脚本停止达到内存限制。我知道我可以增加限制,但由于脚本加载的文件是onlty HTML文件,我解释了限制的达到,只是脚本在每次循环后无法清空内存。我可以通过flush()定期优化我的脚本内存管理吗?

2 个答案:

答案 0 :(得分:4)

通常,您不需要在PHP中手动管理内存,因为它有一个内置于Zend引擎的高级内存管理器,它可以为您完成这项工作。但是,了解一下它是如何工作的,以便更好地理解代码内存不足的原因是很有用的。

作为一个非常基本的概述,PHP根据引用特定数据的变量数量的“引用计数”释放内存。因此,如果您说$a = 'hello'; $b = $a;,包含字符串'hello'的单个内存将具有2的引用计数。如果您对任一变量调用unset(),或者它们超出范围(例如在它们被定义的函数结束时,refcount将减少。一旦refcount达到零,数据将被删除并释放内存。请注意,在这种情况下,“释放”意味着可以释放该PHP脚本的其他部分,而不必释放回操作系统以供其他进程使用。

PHP版本之间存在一些差异值得了解:

  • 如果您有循环引用(例如$obj1->foo = $obj2; $obj2->bar = $obj1;),则上述引用计数机制不起作用,因为引用计数永远不会达到零。在PHP 5.2及更早版本中,这意味着此类循环引用导致内存泄漏,并且必须由程序员手动处理。在PHP 5.3中,添加了"Garbage Collector" 专门用于处理此案例。它不会取代正常的引用计数机制,但如果代码中常见循环引用,则可能值得一读。
  • PHP 5.4包含了对PHP分配和使用内存的方式的大量优化。 AFAIK,这些都没有改变如何编写高效代码的基本建议,如果可以的话,它们只是升级PHP版本的一个很好的理由。

除此之外,还有一些编写PHP代码的常用技巧,可以充分利用内存:

  • 确保在不再需要时丢弃未使用的变量。在结构良好的程序中,这通常不是问题,因为大多数变量将是特定函数的本地变量;当函数退出时,它们将超出范围,并被释放。但是如果要创建大型中间变量或动态创建大量变量,手动调用unset()可能是个好主意。如果您的代码非常线性,或者使用大量的全局和静态变量,只需将其重构为更加模块化的结构,可以提高其内存性能以及可读性,可维护性等。
  • 通过引用($foo = &$bar)分配或传递变量可能会导致PHP使用更多内存而不是直接赋值($foo = $bar)。这是因为PHP使用“Copy On Write”机制将具有相同内容的变量存储在一个内存位置,但引用赋值与此机制冲突,因此PHP必须尽早复制变量。
  • 对象比标量值(int,boolean,string)或数组更需要内存。这是PHP 5.4中已经大大改进的事情之一,但仍然值得考虑 - 尽管显然不排除编写结构良好的代码!

答案 1 :(得分:1)

您可以unset变量,因为您不再需要它们(例如unset($var)$var = null)。如果您使用的是PHP 5.3或更高版本,则还可以显式调用垃圾收集器:请参阅gc_collect_cycles()和gc_enable()。

有些功能似乎比其他功能更差。我最近发现array_merge_recursive()对代码的内存占用做了可怕的事情。

如果您希望能够分析内存的来源,可以使用Xdebug或XHProf / XHGui等工具来提供帮助。例如Xdebug and tracing memory usageProfiling with XHProf

另见:

Force freeing memory in PHP

php garbage collection while script running