3

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

4

2 回答 2

4

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

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

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

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

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

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

您可以取消设置不再需要的变量(例如unset($var)$var = null)。如果您使用的是 PHP 5.3 或更高版本,您还可以显式调用垃圾收集器:参见gc_collect_cycles () 和gc_enable ()。

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

如果您希望能够分析内存的去向,您可以使用 Xdebug 或 XHProf/XHGui 等工具来提供帮助。例如Xdebug 和跟踪内存使用情况以及使用 XHProf 进行分析

也可以看看:

在 PHP 中强制释放内存

脚本运行时的php垃圾收集

于 2013-03-23T12:11:07.270 回答