【问题标题】:php daemon possible memory leakphp守护进程可能存在内存泄漏
【发布时间】:2011-05-06 01:17:45
【问题描述】:

我在 php 中编写了一个守护程序,并希望确保它不会泄漏内存,因为它将 24/7 运行。

即使是守护进程的最简单形式 memory_get_peak_usage 也会报告脚本在每个周期消耗更多内存。另一方面,memory_get_usage 不会增长。

问题是:我应该担心吗?我已经将守护进程剥离到最基本的内容,但这仍在发生。有什么想法吗?

#!/usr/bin/php -q

<?php
require_once "System/Daemon.php";
System_Daemon::setOption("appName", "smsd");
System_Daemon::start();
while(!System_Daemon::isDying()){
 System_Daemon::info("debug: memory_get_peak_usage: ".memory_get_peak_usage());
 System_Daemon::info("debug: memory_get_usage: ".memory_get_usage());
 System_Daemon::iterate(2);
}

最后说明 + 结论:我最终编写了自己的守护进程包装器,而不是使用 pear 的 system_daemon。不管我如何调整这个库,我都无法阻止它泄漏内存。希望这对其他人有帮助。

最后说明 + 结论 2:我的脚本已经投入生产了一个多星期,仍然没有泄漏 1 个字节的内存。所以 - 在 php 中编写一个守护进程实际上似乎是可以的,只要你非常小心它的内存消耗。

【问题讨论】:

  • 分享你的守护进程包装会很棒;)
  • @Xeoncross 抱歉回复晚了。但是很好。它基本上只是一个无休止的while循环,在迭代之前会休眠一段时间。而已。只需确保为每次迭代记录 memory_get_peak_usage() 即可。这样您就可以查看是否有任何内存泄漏。

标签: php memory-leaks daemon


【解决方案1】:

我遇到了同样的问题。也许最好的办法是在PEAR报告新错误

顺便说一句,这样的代码不会显示 memleak:

#!/usr/bin/php -q

<?php
require_once "System/Daemon.php";
System_Daemon::setOption("appName", "smsd");
System_Daemon::start();
while(!System_Daemon::isDying()) {
 print ("debug: memory_get_peak_usage: ".memory_get_peak_usage()."\n");
 print ("debug: memory_get_usage: ".memory_get_usage()."\n\n");
 System_Daemon::iterate(2);

}

看起来 System_Daemon::info() 有问题。

【讨论】:

    【解决方案2】:

    原来file_get_contents 正在泄漏内存。每当我禁用那一行时,峰值内存使用量就很稳定。当我重新评论它时,每次迭代的峰值内存使用量将增加 32 个字节。

    Replacedfile_get_contents调用file_get_contents(用于检索/var/run中的pid文件内的数字)与fread,解决了这个问题。

    此补丁将成为下一个 System_Daemon 版本的一部分。

    感谢谁(找不到匹配的昵称)也报告了这个错误(#18036),否则我可能永远不会知道。

    再次感谢!

    【讨论】:

      【解决方案3】:

      您可以尝试使用 PHP 5.3 中的新垃圾收集器来防止循环引用问题。

      【讨论】:

      • 仅供参考,我们编写了一个用于 tweetsms.com 的“守护进程”脚本。这是一个 PHP 5.3 脚本,它使用 Doctrine(DB ORM 映射器),启动其他命令,并将日志消息保存到数据库(通过教义)。我今天检查了,守护进程已经运行了 4 个多月,并且没有增加任何内存使用量。我们在每个循环之后调用 gc_collect_cycles() 以防万一。
      【解决方案4】:

      你不应该use PHP to write a daemon。为什么?因为 PHP 不是一种足够成熟的语言,可以运行数小时、数天、数周或数月。 PHP 是用 C 语言编写的,它提供的所有魔力都必须处理。根据您的版本,垃圾收集可能会或可能不会起作用,具体取决于您编译和使用的扩展。是的,如果他们随官方版本一起发布,他们应该“玩得很好”,但是您是否检查一下您使用的是哪个版本?您确定所有加载的扩展程序都意识到它们可能会运行超过 10 到 30 秒吗?鉴于大多数执行时间从不发现泄漏,你确定它甚至可以工作吗?

      关于这个问题,我非常接近于“don't use regex to parse HTML rant”,因为我看到这个问题越来越多。我知道今天有两次。

      你会用撬棍作为牙签吗?考虑到呈现网页时 PHP 进程的预期寿命,Zend、Roadsend 和 PHC 都不够成熟,无法处理任何可能被认为是延长的时间段的运行。是的,即使使用基于 C++ 的 PHP 编译器提供的 GC 工具,在 PHP 中编写守护程序也是不明智的。

      我讨厌说 you can't do that, with that 的答案,但在这种情况下,这是真的,至少现在是这样。

      【讨论】:

      • 你可能是对的,我只是碰巧用 php 比说 c 好得多。它会执行一个相当简单的任务,所以我可能会试一试。将让它在开发盒上运行一周左右。
      • 我不确定 PHP 5.3 是否如此。由于我们进行了循环垃圾收集,即使在重负载下,我也能在长时间运行的 PHP(天)守护程序方面取得良好的成功。虽然 PHP 对守护进程的支持确实很差,但我正在尝试使用 LooPHP 来改变它。
      • @Kendall Hopkins - 几乎所有关于 SO 的答案都在提出问题的时间附近得到了回答,只有少数例外。到今天为止,我的建议仍然是,不要将 PHP 用于系统进程。如果你这样做了,请确保 PHP 的一个令人满意的版本正在运行,如果 PHP 展示了一个稳定和工作的 GC。您可以考虑添加答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-14
      • 2012-09-23
      • 2020-06-12
      • 2011-07-18
      • 1970-01-01
      相关资源
      最近更新 更多