【问题标题】:Strategies for handling memory consumption in PHP5?在 PHP5 中处理内存消耗的策略?
【发布时间】:2010-09-18 21:41:54
【问题描述】:

我们有一个大型管理软件,它基于大量循环生成各种大型报告,包括数据库检索、对象创建(许多)等等。

在 PHP4 上,它可以在内存限制为 64 MB 的情况下愉快地运行 - 现在我们已经将它移动到新服务器上并使用相同的数据库 - 相同的代码,相同的报告不会在没有内存限制的情况下出现。 ..

我知道 PHP5 在底层发生了很多变化,但有没有办法让它正常运行?

最后的问题是,当你需要让你的剧本节食时,你会采用什么策略?

【问题讨论】:

    标签: php memory


    【解决方案1】:

    自从迁移到新服务器后,您是否确认您的 MySQL 和 PHP 系统变量与旧服务器上的方式相同?

    PHP5 引入了许多新功能,但由于其向后兼容的口头禅,我不认为 PHP5 和 PHP4 之间的差异应该对代码和数据库尚未更新的应用程序的性能造成如此大的影响改变了。

    您是否也在相同版本的 Apache 或 IIS 上运行?

    这听起来更像是与您的新系统环境相关的问题,而不是从 PHP4 升级到 5 的问题。

    【讨论】:

      【解决方案2】:

      伯特兰,

      如果您有兴趣重构现有代码,那么我建议您在执行报告时首先监控 CPU 和内存使用情况。您是锁定 SQL 服务器还是锁定 Apache(如果 PHP 代码对系统施加了很大压力,就会发生这种情况)?

      我从事的一个项目最初严重阻碍了 MySQL,以至于我们不得不重构整个报告生成过程。然而,当我们完成时,负载只是简单地转移到了 Apache(通过更复杂的 PHP 代码)。我们最终的解决方案是重构数据库设计,为报告功能提供更好的性能,并使用 PHP 来弥补我们在 MySQL 中无法实现的功能。

      根据报告的性质,您可能会考虑对用于报告的数据进行非规范化处理。您甚至可以考虑构建第二个数据库,用作数据仓库并围绕 OLAP 原则而不是 OLTP 原则设计。您可以从 Wikipedia 开始了解 OLAP 和数据仓库的一般说明。

      但是,在开始认真重构之前,您是否通过查看 phpinfo(); 来验证您的环境是否足够相似?用于 PHP 和显示变量; 在 MySQL 中?

      【讨论】:

        【解决方案3】:

        我们遇到的一个大问题是对象之间的循环引用阻止它们在超出范围时释放内存。

        根据您的架构,您可以使用 __destruct() 并手动取消设置任何引用。对于我们的问题,我最终重组了类并删除了循环引用。

        【讨论】:

          【解决方案4】:

          当我需要优化任何脚本的资源时,我总是尝试分析、分析和调试我的代码,我使用 xDebugxDebug Profiler,还有其他选项,例如 APDBenchmark Profiler .

          另外我推荐你这篇文章:

          【讨论】:

            【解决方案5】:

            演出!?!

            即使 64MB 也很大。

            忽略环境之间的差异(听起来确实很奇怪),听起来代码可能需要一些重构。

            您有机会重构您的代码,以便数据库查询的结果集不会转储到数组中。我建议您为结果集构建一个迭代器。 (因此您可以在大多数情况下将它们视为数组)。一次处理一条记录与一次处理 10,000 条记录之间存在很大差异。

            其次,看看你的代码创建多个数据实例的天气。你能通过引用传递对象吗? (使用 '&')。在使用 horde 框架的早期变体时,我们必须做类似的事情。一个 1 MB 的附件会因多次调用而膨胀到 50 MB,这些调用将整个数据集作为副本而不是作为参考传递。

            【讨论】:

            • PHP5中的对象是通过引用自动传递的。
            • 真的吗?!那不会破坏范围的想法。如果将对象传递给函数,则该函数正在对象的副本上操作,而不是实际对象。 (除非您通过引用传递对象。)
            • @grantwparks 所说的只是一个粗略的简化...php.net/manual/en/language.oop5.references.phpOne of the key-points of PHP 5 OOP that is often mentioned is that "objects are passed by references by default". This is not completely true. This section rectifies that general thought using some examples.
            • 它不是对对象的副本进行操作;如果您对传递给函数的对象进行更改,则该对象将被更改。创建并传递了一个新的“引用/句柄/标识符”(因此根本不传递对象)。该引用所使用的内存应该与对象的大小无关。 @user1548557 称之为粗略的简化,我称之为处理内存时所有意图和目的的实际效果。 php.net 页面上有很多混乱并不意味着这很复杂。
            • 除非您明确传递引用,否则您建议的行为只会在特定情况下发生并且不会保留更深层次的对象结构,PHP.net 文档同意我的观点,您甚至描述承认对象未通过引用传递的过程,请查看 CS101
            猜你喜欢
            • 2016-09-24
            • 1970-01-01
            • 2012-11-06
            • 2018-10-22
            • 2019-05-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多