2013-03-23 155 views
1

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

+0

如果您显示的代码,也许有人可以发现内存不是free'd。 'flush()'用于处理输出缓冲区。 – alex 2013-03-23 11:54:20

+0

请注意PHP版本号。内存管理在PHP 5.2及更早版本中有很大不同。 – cleong 2013-03-23 11:55:44

+0

我的问题与我的脚本无关。我只是想在概念上理解何时需要在代码中明确释放内存。 – CptNemo 2013-03-23 12:00:22

回答

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

+1

请注意,PHP垃圾收集器仅用于**循环引用的特例;它不是** Zend引擎中的主要内存管理机制。 – IMSoP 2013-03-23 12:59:23

+0

是的,好的,@IMSoP。更多信息请登录http://php.net/manual/en/features.gc.performance-considerations.php和http://php.net/manual/en/features.gc.collecting-cycles.php查看感兴趣的人。 – 2013-03-23 13:49:31

3

一般情况下,你不应该需要PHP手工管理内存,因为它内置了一个高层次的内存管理器到Zend引擎,为你照顾这件事。但是,了解一下这个过程是如何工作的,以便更好地理解你的代码为什么会耗尽内存是非常有用的。

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

有PHP版本价值之间的一些差异知道:

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

除此之外,还有编写PHP代码,使良好的使用内存的几个常见提示:

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