如何阻止PHP输出缓冲区超过内存限制?

时间:2008-11-11 17:17:39

标签: php memory

我的大多数PHP应用程序在开头都有一个ob_start,遍历所有代码,然后在完成所有操作后输出内容,有时会进行一些修改。

ob_start()
//Business Logic, etc
header->output();
echo apply_post_filter(ob_get_clean());
footer->output();

这可确保PHP错误显示在网站的内容部分中,并且错误不会干扰headersession_*来电。

我唯一的问题是,有些大页面PHP内存不足。我该如何阻止这种情况发生?

一些想法:

  1. 将所有缓冲内容写入临时文件并输出。
  2. 当缓冲区达到一定大小时,输出它。虽然这可能会影响后置过滤器。
  3. 提高内存限制(thanx @troelskn)。
  4. 这些方法的缺点是什么?特别是提高内存限制?

5 个答案:

答案 0 :(得分:6)

你不能提高内存限制吗?听起来对我来说是最好的解决方案。

编辑:很明显,仅仅因为脚本最高限度而提高内存限制应该会引起一些危险信号,但这听起来像是一个合法的案例 - 例如。该脚本实际上产生了相当大的输出块。因此,您必须将输出存储在某处,并且出于性能和便利的原因,内存似乎是最佳选择。

我还应该注意内存限制设置就是 - 限制。不消耗大量内存的脚本不会因为提高限制而消耗更多内存。它存在的主要原因是防止行为不端/错误的脚本取下整个服务器。如果你有很多业余爱好者在共享主机上进行攻击,那么这一点非常重要(PHP已被大量使用)。因此,如果这是您自己的服务器,或者至少您通常知道自己在做什么,那么内存限制不会带来任何好处。

答案 1 :(得分:2)

你应该在任何事情之前提高内存限制,特别是如果你唯一的其他解决方案是通过一个临时文件。

使用临时文件有各种各样的缺点(主要是速度较慢),如果你真的需要一种方法来存储缓冲区,那么Go会查找memcachedAPC cache。除了可以快速访问RAM外,这可以让你和文件大致相同。

不过,我必须说这是一个可怕的想法。如果缓冲区当前不能正常工作,那么您可能可以采用不同的方式构建一些内容,以使您的网站更好地工作。

答案 2 :(得分:2)

如果php错误是缓冲输出的唯一原因,请考虑使用set_error_handler。使用此功能,您可以为脚本中的错误定义自定义回调。用它来保存消息,然后再打印出来。

http://www.php.net/set_error_handler

答案 3 :(得分:1)

由于输出导致内存不足,您必须输出大量数据或内存限制非常低。大约4年前,内存限制为8mb是足够普遍和合理的。但是,随着切换到使用对象和更好的编码样式,我遇到的脚本的内存使用量已经增加。

Hrm ......你的脚本内存耗尽在哪里?如果它总是在您的输出过滤功能中,他们可能只需要进行优化吗? memory_get_usage()将返回脚本在此时使用的内存量。

您目前的内存限制是多少?你在共享环境中运行吗? 目前我的内存限制在64到128之间,具体取决于服务器。

如果它只是一个特定的脚本子集,你想增加当时的限制,你可以按脚本执行:

ini_set('memory_limit','64M');

如果您不想对脚本进行限制,可以将其设置为-1

答案 4 :(得分:1)

我的建议是尝试分阶段加载文件,或者将其拆分成较小的部分以便包含。你如何做到这在很大程度上取决于文件是什么,但它允许你加载说... 2mb块,如果它没有产生任何错误然后你使用ob_flush()发送它之前加载下一个块。

例如,你提到它是一个PHP模板;我不确定究竟会是什么,如果你在谈论一个混合的PHP / HTML文件,当执行时产生输出,那么你可以尝试在模板中添加某种形式的块标记来分离模板的不同部分。这样,您只需要读取当前块的末尾,然后输出并继续。如果你有循环等,这会变得更加困难,但通常总会有办法解决它。例如,通过在模板中添加PHP,触发主脚本中可以分阶段处理循环输出的方法/函数。

您可能还希望在加载模板之前查看预先验证模板的机制,因此您根本不必担心错误进入页面。

虽然更改内存限制将在短期内“解决”问题,但这不是一个长期解决方案,因为如果可能的话,绝对要避免使用这种内存。一般情况下,如果你可以避免将任何大的内容加载到内存中,或者尽早将其吐出,因为这意味着数据至少在向用户发送的过程中减少了首次使用的时间。页面的字节。