From: "Robert T. Covell" on
We are running Mail_Queue in an application using System_Deamon.

In other deamons that we run we have found out that they do not die if
we regularly recycle our mysql database connections. We tried to do
this with Mail_Queue by randomly creating a new object every 1 to 3
seconds.

$mail_queue =& new Mail_Queue($db_options, $mail_options);

Followed by:

$mail_queue->sendMailsInQueue($max_amount_mails);


The issue is that peak memory usage grows by .25 MB every 30 seconds
(resident memory also grows accordingly), which will eventually take up
all resources on the server.

If we do not recycle Mail_Queue, peak memory usage stays at 3.75 MB and
19MB for resident memory. The deamon will stay up for an undetermined
amount of time in this setup.

Is there a way to safely recycle the database connection or Mail_Queue?

Thanks in advance,
-Bob
From: Alister Bulman on
On Thu, Mar 26, 2009 at 3:23 PM, Robert T. Covell <rcovell(a)rolet.com> wrote:
> In other deamons that we run we have found out that they do not die if
> we regularly recycle our mysql database connections.
>
> $mail_queue =& new Mail_Queue($db_options, $mail_options);
> Followed by:
> $mail_queue->sendMailsInQueue($max_amount_mails);
>
> The issue is that peak memory usage grows by .25 MB every 30 seconds
> (resident memory also grows accordingly), which will eventually take up
> all resources on the server.
> ....
> Is there a way to safely recycle the database connection or Mail_Queue?

I had a similar problem, and there's two things I used to get around it.

1/ use xdebug's memory reporting (or now memory_get_usage()) to find
where the variables are being used that expand memory, but are not
being cleared down (unset-ting them). That might help a lot, but
cleaning up regularly will help a lot more (5.3 should help with that
as well).

2/ I have been sending over 100,000 mails in a few hours by having a
script that repeatedly calls $mail_queue->sendMailsInQueue();, but
when it's sent 'enough' (say 5000 at a time) - or it just fails for
any other reason, it will exit the script and then be restarted by a
bash script that wraps the php file. When the PHP script exits, memory
is cleaned up, and it's good to go again. It's not a daemon, just a
bash script - but you can call it as "nohup ./sendMails.sh &" to keep
it running in the background.

I'd suggest you use exit($val) with one of two different values - one
for an immediate restart, and any other value for a slight pause, say
2-10 secs. I've also added in the PHP script a check of the machine's
load average - too high and it sleeps in a loop till it's good to run.
It works well for me, and with the LdAvg check, I can leave it to
send as many as I like,knowing it will be safe to leave to get on with
it.

Since Mail_Queue runs right out the the DB, exiting the PHP script
that calls it is quite safe, as it's either been sent and deleted, or
it's still waiting to go (maybe some time in the future).

Alister
From: Kevin van Zonneveld on
On Thu, Mar 26, 2009 at 6:29 PM, Alister Bulman <abulman(a)gmail.com> wrote:
> On Thu, Mar 26, 2009 at 3:23 PM, Robert T. Covell <rcovell(a)rolet.com> wrote:
>> We are running Mail_Queue in an application using System_Deamon.
>>
>> ...
>>
>> The issue is that peak memory usage grows by .25 MB every 30 seconds
>> (resident memory also grows accordingly), which will eventually take up
>> all resources on the server.

I noticed my package System_Daemon in the conversation.

This isn't really a System_Daemon problem, but maybe I can still
clarify a thing or two, cause you are not alone in this issue.

Some classes keep a history of executed commands, sent mails,
whatever. They were designed without knowing they would ever be used
in a daemonized environment.
Cause daemons run indefinitely this 'history' will expand
indefinitely. Since unfortunately your server's RAM is not infinite,
you will run into problems at some point.

This makes it's very important to address these memory 'leaks' when
building daemons.

If you can't/won't change the code that causes the leak, you will have
to resort to more ugly (but effective) measures.

One solution could be to reinstantiate your class every once in a
while, or enclose the problematic code inside a function (or even a
separate script?) without globals. Or maybe you can explicitly purge
that history or counter, or whatever is growing without limit.

If the class still floods global variables you don't have control
over, there always is
System_Daemon::restart();
which was introduced in v0.6.0
You could call it after a certain memory_get_usage() has been reached.
It will kill it's own process and spawn another one. Freeing up all
memory. Like I said: ugly, but very effective.

This should really be your last resort as fixing the problem is better
then containing it.
Maybe a developer of Mail_Queue can help you with that?

--
Met vriendelijke groet / Kind regards,

Kevin van Zonneveld
http://kevin.vanzonneveld.net
From: "Robert T. Covell" on
I was going to implement a form of what Alister suggested.

Have a cronjob that checks for the pid and if it is not running just
restart it.

I think your suggestion of checking for a certain amount of memory usage
and then restarting the deamon might be a better implementation to
achieve the same results. This way I can have the deamon control itself
and recycle the database connections (per another email discussion for
System_Deamon) and ensure that the deamon does not die. Not sure what
an acceptable value would be for memory usage (100MB?). If I extend the
database recycle time I could slow the growth.

Thanks for all the suggestions...

-Bob

> -----Original Message-----
> From: vanzonneveld(a)gmail.com [mailto:vanzonneveld(a)gmail.com] On Behalf
Of
> Kevin van Zonneveld
> Sent: Friday, March 27, 2009 8:19 AM
> To: Alister Bulman
> Cc: pear-general(a)lists.php.net
> Subject: Re: [PEAR] Mail_Queue Memory Usage/DB Connection
>
> On Thu, Mar 26, 2009 at 6:29 PM, Alister Bulman <abulman(a)gmail.com>
wrote:
> > On Thu, Mar 26, 2009 at 3:23 PM, Robert T. Covell
<rcovell(a)rolet.com>
> wrote:
> >> We are running Mail_Queue in an application using System_Deamon.
> >>
> >> ...
> >>
> >> The issue is that peak memory usage grows by .25 MB every 30
seconds
> >> (resident memory also grows accordingly), which will eventually
take up
> >> all resources on the server.
>
> I noticed my package System_Daemon in the conversation.
>
> This isn't really a System_Daemon problem, but maybe I can still
> clarify a thing or two, cause you are not alone in this issue.
>
> Some classes keep a history of executed commands, sent mails,
> whatever. They were designed without knowing they would ever be used
> in a daemonized environment.
> Cause daemons run indefinitely this 'history' will expand
> indefinitely. Since unfortunately your server's RAM is not infinite,
> you will run into problems at some point.
>
> This makes it's very important to address these memory 'leaks' when
> building daemons.
>
> If you can't/won't change the code that causes the leak, you will have
> to resort to more ugly (but effective) measures.
>
> One solution could be to reinstantiate your class every once in a
> while, or enclose the problematic code inside a function (or even a
> separate script?) without globals. Or maybe you can explicitly purge
> that history or counter, or whatever is growing without limit.
>
> If the class still floods global variables you don't have control
> over, there always is
> System_Daemon::restart();
> which was introduced in v0.6.0
> You could call it after a certain memory_get_usage() has been reached.
> It will kill it's own process and spawn another one. Freeing up all
> memory. Like I said: ugly, but very effective.
>
> This should really be your last resort as fixing the problem is better
> then containing it.
> Maybe a developer of Mail_Queue can help you with that?
>
> --
> Met vriendelijke groet / Kind regards,
>
> Kevin van Zonneveld
> http://kevin.vanzonneveld.net
>
> --
> PEAR General Mailing List (http://pear.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php

From: Kevin van Zonneveld on
On Fri, Mar 27, 2009 at 2:51 PM, Robert T. Covell <rcovell(a)rolet.com> wrote:
> Have a cronjob that checks for the pid and if it is not running just
> restart it.

There's a better solution for that too: monit
you can have a simple config file like this:

check process <daemon name> with pidfile /var/run/<daemon
name>/<daemon name>.pid
start program = "/etc/init.d/<daemon name> start"
stop program = "/etc/init.d/<daemon name> stop"
alert rcovell(a)example.com

Or a very complex one (have a look at /etc/monit/monitrc)

> I think your suggestion of checking for a certain amount of memory usage
> and then restarting the deamon might be a better implementation to
> achieve the same results.

Probably. I don't know what your mem_limit is for PHP, but it isn't
reasonable for a simple daemon to claim so much memory it doesn't
actually use. This memory is taken away from other things on your
system (like cache, and will slow down your entire server).

> Not sure what
> an acceptable value would be for memory usage (100MB?).  If I extend the
> database recycle time I could slow the growth.

That depends of course. I don't know Mail_Queue, your data, or your
server. But why don't you see what it can achieve with 100MB for
starters, and maybe go up from there. Keep an eye on '# free -m' to
see if your server has RAM to spare or starts swapping already.

I hate it to repeat myself, but please understand that it's much
better to plug the leak if you can.

--
Met vriendelijke groet / Kind regards,

Kevin van Zonneveld
http://kevin.vanzonneveld.net