3

i've written a daemon in php and want to make sure it doesn't leak memory, as it'll be running 24/7.

even in its simplest form memory_get_peak_usage for a daemon will report that the script consumes more memory for each cycle. memory_get_usage on the other hand will not grow.

the question is: should i worry? i've stripped down the daemon to the bare basics but this is still happening. any thoughts?

#!/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);
}

FINAL NOTE + CONCLUSION: i ended up writing my own daemon wrapper, not using pear's system_daemon. regardless of how i tweaked this library i could not stop it from leaking memory. hope this helps someone else.

FINAL NOTE + CONCLUSION 2: my script has been in production for over a week and is still not leaking 1 bytes of memory. so - writing a daemon in php actually seems to be ok, as long as you're very careful about its memory consumtion.

fjallstrom
  • 145
  • 1
  • 2
  • 10
  • Sharing your daemon wrapper would be awesome ;) – Xeoncross Sep 09 '11 at 23:10
  • 1
    @Xeoncross sorry for late reply. but yeah well. it basically just is an endless while loop that usleeps a while before iterating. nothing more. just make sure to log memory_get_peak_usage() for each iteration. that way you'll see if you have any memory leaks. – fjallstrom Feb 06 '12 at 22:29

4 Answers4

5

I got the same problem. Maybe the best idea is to report new bug at PEAR

BTW, code like that doesn't show that 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);

}

Look's like System_Daemon::info() is a problem.

kkszysiu
  • 537
  • 2
  • 8
4

It turns out file_get_contents was leaking memory. Whenever I disabled that one line, peak memory usage was stable. When I commented it back in, peak memory usage would increase by 32 bytes every iteration.

Replaced the file_get_contents call (used to retrieve the number inside the pid-file in /var/run) with fread, and solved this problem.

This patch will be part of the next System_Daemon release.

Thanks whoever (can't find matching nick) also reported this bug (#18036) otherwise I'd probably never known.

Thanks again!

kvz
  • 5,517
  • 1
  • 42
  • 33
2

You can try using the new garbage collector in PHP 5.3 to prevent issues with circular references.

scrowler
  • 24,273
  • 9
  • 60
  • 92
CAMason
  • 1,122
  • 7
  • 13
  • FYI, we wrote a 'daemon' script that's used on tweetsms.com. It's a PHP 5.3 script that uses Doctrine (DB ORM mapper), launches other commands, and saves log messages to the DB (via doctrine). I checked today, and the daemon had been running for over 4 months and not increased any memory usage. We call gc_collect_cycles() after each loop just incase. – CAMason Nov 07 '10 at 23:40
0

You should not use PHP to write a daemon. Why? Because PHP is not a language that is sufficiently mature to run for hours, days, weeks or months. PHP is written in C, all of the magic that it provides has to be handled. Garbage collection, depending on your version, might or might not work, depending on what extensions you have compiled and used. Yes, if they ship with official releases, they should 'play nice', but do you check to see what release you are using? Are you sure all loaded extensions realize that they might run for more than 10 - 30 seconds? Given that most execution times never spot leaks, are you sure it even works?

I am quite close to going off on a 'don't use regex to parse HTML rant' regarding this, as I see the question creeping up more and more. Twice today that I'm aware of.

Would you use a crowbar as a toothpick? Neither Zend, nor Roadsend, Nor PHC is sufficiently mature to handle running for any period of time that could be considered protracted, given the expected life of a PHP process when rendering a web page. Yes, even with the GC facilities provided by C++ based PHP compiler, it is unwise to write a daemon in PHP.

I hate answers that say you can't do that, with that, but in this case, it's true, at least for now.

Community
  • 1
  • 1
Tim Post
  • 33,371
  • 15
  • 110
  • 174
  • you are probably right, i just happen to be much better with php than say, c. it will perform a fairly simple task so i will probably give it a go anyway. will leave it running for a week or so, on a dev box. – fjallstrom Nov 07 '10 at 18:28
  • 3
    I'm not sure if this is true with PHP 5.3. Since we got circular garbage collection, I've had good success with long running PHP (days) daemons even under heavy load. While it's true that PHP has very poor daemon support, I'm trying to change that with [LooPHP](https://github.com/Wordi/LooPHP). – Kendall Hopkins Nov 25 '10 at 05:48
  • 2
    @Kendall Hopkins - Almost every answer on SO was answered near the time that the question was asked, with a few exceptions. As of today, my advice remains, do not use PHP for system processes. If you do, ensure an agreeable version of PHP is running, should PHP demonstrate a stable and working GC. You might consider adding an answer. – Tim Post Nov 25 '10 at 19:02