【问题标题】:PHP Memory ManagementPHP 内存管理
【发布时间】:2011-03-21 02:23:28
【问题描述】:

我的 LAMP Web 应用程序中有一些耗时且(可能)占用大量内存的功能。这些函数中的大部分将通过 cron 每分钟执行一次(在某些情况下,cron 作业将执行这些函数的多个实例)。

由于内存是有限的,我不想在尝试执行环境无法再处理的功能时遇到问题。 什么是处理潜在记忆问题的好方法?

我猜我需要确定有多少内存可供我使用,每个函数在执行之前需要多少内存,确定 cron 正在执行哪些其他函数及其内存用法等。

另外,我不想遇到某个函数以某种方式获得执行优先于其他函数的问题。如果有任何优先级,我想以某种方式控制它。

【问题讨论】:

  • 更重要的是,您为什么每 分钟 执行一次 Cronjob?他的部分问题可能是 cron 只是试图一次做太多事情。如果您可以解释问题和您提出的解决方案,我们将能够为您的特定内存问题提供更好的答案。针对不同的问题有不同的方法。是不是数据库中的数据很多?平面文件?仅仅是大量的数学计算?每个人都有自己的一组优化步骤。请充实您的问题,以便我们做出适当的回应:)。
  • 我认为您需要更具描述性并说明您在此 cron 工作中所做的工作。明显的节省是不将大文件加载到内存中进行处理,使用流函数,将大型数据库结果集拉入内存,使用游标对记录集进行操作而不是将所有数据拉入数组等。

标签: php memory memory-leaks memory-management


【解决方案1】:

您可以使用memory_get_usage 了解您的脚本当前使用了多少内存 但是在执行它之前,您无法确定下一个函数需要多少。你只能在执行后看到,使用memory_get_usage。但是,您可以将函数上次使用的内存存储在数据库中,并使用平均内存量进行计算。

关于执行优先级,我认为用 PHP 确定是不可能的。 Apache(或您正在使用的任何网络服务器)生成多个进程,并且操作系统会安排哪个进程以何种顺序执行。

【讨论】:

  • memory_limit 定义了每个 php 进程可以吃多少内存。它在您的 php.ini 文件中。默认为 8 或 16 MB。您可以随时将其更改为更大的值,直到您有足够的系统内存 (+swap)。
【解决方案2】:

在你的位置上,我会考虑编写一个守护进程而不是依赖 cron。守护进程可以监视一个队列并知道它正在运行的子进程的数量。管理多个进程绝对不是 php 的最大优势,而是you can do it。 Pear 甚至包含一个System_Daemon 包。

您的守护进程可以使用memory_get_usage 并调用freeuptime 和朋友来限制工作人员的数量以匹配系统条件。

我对此没有任何直接经验,如果用 PHP 编写的守护程序逐渐泄漏内存,我也不会太惊讶。但是如果它的速度可以接受的话,cron 可以经常循环守护进程......

【讨论】:

  • ...我猜子进程可能必须调用memory_get_usage 并将结果传达给父进程...或者父进程可能会调用pstop。 ..
【解决方案3】:

您可以研究像 APC 这样的缓存技术,它可以让您将内容直接写入 RAM,以便您可以快速访问它,如果您不想重复执行 mysql 查询等昂贵的任务。

我能想到的一个缓存示例是,您可以缓存电子邮件,而不是从电子邮件服务器一次又一次地检索它们。如果您的脚本中有一些东西要在下次脚本执行时保留,但如果您的脚本每次执行时都做独特的事情,那么基本上 ram 缓存是一种非常有用的技术,那将是无用的。同样对于 contoll,您可以在每次脚本执行时调用 memory_get_usage() 并将该值写入 apc 缓存,以便每个 cron 都可以检索该值并查看是否有足够的可用内存来完成。

至于平均使用量,您可以编写一个数组,最后让我们说 100 次函数执行,当您再次调用该函数时,它可以从 ram 中 apc_fetch 并计算该函数的平均内存使用量,然后将其与多少 ram 进行比较现在正在使用,然后决定是否开始。此外,它可以将该估计值写入当前内存使用变量,以防止运行其他脚本。在该函数的末尾,您再次从变量中减去该数量。 tl;博士: 查看 apc_fetch、apc_store 和 memory_get_usage 函数

【讨论】:

  • 内存负担任务与 MySQL 无关。大部分与图像处理、PDF 处理、从 FTP 服务器下载和上传文件、发送和检索电子邮件等有关。
【解决方案4】:

尝试优化您的算法。喜欢...

  • 一旦你完成了一个变量,如果你不再需要它,你应该销毁它。
  • 完成后关闭 MySQL 连接。
  • 使用递归。

正如 Jauzsika 所说,更改 php.ini 中的内存限制,但不要让它太高。如果您需要超过 256MB 的 RAM,那么我建议您更改为其他语言而不是 PHP。

【讨论】:

  • 鉴于他没有描述他的代码在做什么,我认为你不能指定 256MB 的任意限制。
  • 所有变量都被销毁,所有数据库连接都关闭,递归不是一个选项。 256mb 是任意的。没有理由切换语言。我只需要一种方法来确保我不会无意中使用太多内存。
【解决方案5】:

您的问题的一部分可能是您每分钟都在执行 cron 的事实?为什么不设置一些标志,以便该 cron 的一个实例在另一个实例执行完整逻辑之前运行?即创建一个在 cron 末尾删除的平面文件以充当“锁”。这将确保一个 cron 进程在其他任何进程继续之前完全完成。但是,我敦促您参考我对您帖子的评论,以便我和其他人可以给您更可靠的建议。

【讨论】:

  • 假设我有正当理由每分钟运行一次 cron 作业。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2011-06-05
  • 2011-07-21
  • 2012-03-21
相关资源
最近更新 更多