【问题标题】:How to stop a PHP output buffer from going over the memory limit?如何阻止 PHP 输出缓冲区超出内存限制?
【发布时间】:2010-09-21 20:16:56
【问题描述】:

我的大多数 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)。

这些方法的缺点是什么?尤其是提高内存限制?

【问题讨论】:

    标签: php memory


    【解决方案1】:

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

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

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

    【讨论】:

    • 我试过了,但我体内的某些东西会提高内存限制。提高内存限制有什么缺点吗?
    【解决方案2】:

    您应该先提高内存限制,尤其是当您唯一的其他解决方案是通过临时文件时。

    使用临时文件有各种各样的缺点(主要是速度较慢),如果您真的需要在输出之前存储缓冲区的方法,请查找memcachedAPC cache。这可以让你做的事情与文件大致相同,只是你可以快速访问 RAM。

    不过,我必须说这总体上是一个糟糕的主意。如果缓冲区当前无法正常工作,您可能需要构建一些不同的东西以使您的网站更好地工作。

    【讨论】:

      【解决方案3】:

      如果 php 错误是缓冲输出的唯一原因,请考虑使用 set_error_handler。使用此函数,您可以为脚本中的错误定义自定义回调。使用它将消息保存在某处并稍后打印。

      http://www.php.net/set_error_handler

      【讨论】:

      • 这不仅仅是因为错误。注意改变输出的 apply_post_filter 函数。
      【解决方案4】:

      我的建议是尝试分阶段加载文件,或将其分成更小的部分以包含在内。您如何执行此操作将在很大程度上取决于文件是什么,但它允许您以 2mb 块的形式加载它,如果它没有产生任何错误,那么您可以在加载下一个块之前使用 ob_flush() 发送它。

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

      您可能还想了解一种在加载模板之前预先验证模板的机制,这样您就完全不必担心错误会蔓延到页面中。

      虽然更改内存限制会在短期内“解决”问题,但它不是长期解决方案,因为如果可能的话,肯定要避免这种内存使用。一般来说,如果可以避免的话,您根本不想将任何大的东西加载到内存中,或者尽早将其吐出,因为这意味着数据至少正在发送给用户的途中,从而减少了首次使用的时间页面的字节。

      【讨论】:

        【解决方案5】:

        如果您因输出而耗尽内存,则必须有大量数据流出或内存限制非常低。大约 4 年前,8mb 的内存限制已经足够普遍且合理。但是随着切换到使用对象和更好的编码风格,我遇到的脚本的内存使用量有所增加。

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

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

        如果它只是您想要增加限制的特定脚本子集,那么您可以按脚本执行:

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

        如果您不希望脚本限制,可以将其设置为 -1

        【讨论】:

        • 服务器是一些非常大的网络应用程序的生产服务器。我认为内存限制是 128Mg。当我将一个非常大的 PHP 模板文件加载到缓冲区中时,我达到了极限。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        相关资源
        最近更新 更多