It's been a while since a release so one is coming soon
[BUGFIXED] How to destroy Swift_Message object? bug?
Moderators: Chris Corbyn, General Moderators
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
I stumbled upon this thread while attempting to trace the leak that started after an upgrade from 2.1 to 3.2.6_4, so now I have the svn copy, and that's much better, but I still seem to have a leak . The leak is little, and I would not have noticed it had I not put in debug code for the big leak, but just to follow up.
In this loop I get a constant building of memory, the functions only create 3 ints each, and would have no hanging objects. I think I have unset everything in the loop. Would the unset problem extend to other classes such as Swift_Address?
I have pulled all the constructed objects out of line so that I can unset them by name, but I still seem to have a slow leak.
SHOULD unsetting a message unset all its parts? For instance if $part1 and $part2 were instead constructed as inline new objects should an unset to $message free them as well?
here is the memory as it grows on a part of a block of test addresses. The change is not constant per iteration( around 300B). Am I just looking at logging data growth, or is this likely from something not unset in the loop itself?
If it is some sort of logging data that swift is generating can i get rid of it(or at least everything but the failed addresses)?
NOTE: I have swift disk caching turned on and most of the memory ~5MB use is in my recipient array.
In this loop I get a constant building of memory, the functions only create 3 ints each, and would have no hanging objects. I think I have unset everything in the loop. Would the unset problem extend to other classes such as Swift_Address?
I have pulled all the constructed objects out of line so that I can unset them by name, but I still seem to have a slow leak.
SHOULD unsetting a message unset all its parts? For instance if $part1 and $part2 were instead constructed as inline new objects should an unset to $message free them as well?
Code: Select all
foreach($recipients as $recipient)
{
$body_txt = customize_mail( $array_txt , $recipient[$SUBSCRIBER_FIRST_NAME] , $recipient[$SUBSCRIBER_LAST_NAME],recipient[$SUBSCRIBER_EMAIL] );
$swift_mail_to =& new Swift_Address("$recipient[$SUBSCRIBER_EMAIL]", "$recipient[$SUBSCRIBER_FIRST_NAME]" . " " . "$recipient[$SUBSCRIBER_LAST_NAME]");
$message =& new Swift_Message("$mail_subject");
$part1 =& new Swift_Message_Part("$body_txt");
$message->attach($part1);
if ( $has_html)
{
$body_html = customize_mail( $array_html , $recipient[$SUBSCRIBER_FIRST_NAME] , $recipient[$SUBSCRIBER_LAST_NAME] , $recipient[$SUBSCRIBER_EMAIL] );
$part2 =& new Swift_Message_Part("$body_html", "text/html");
$message->attach($part2);
}
if($mailer->send($message,$swift_mail_to, $swift_mail_from))
print "<font face='arial' size='2'>mail sent to $recipient[$SUBSCRIBER_EMAIL]...</font><br>";
else
print "<font face='arial' size='2'>mail could not be sent to $recipient[$SUBSCRIBER_EMAIL]...</font><br>";
unset($part1);
unset($part2);
unset($message);
unset($swift_mail_to);
unset( $body_html);
unset( $body_txt);
$mem = memory_get_usage();
print "using $mem memory at $recipient[$SUBSCRIBUR_EMAIL]";
} // for eachIf it is some sort of logging data that swift is generating can i get rid of it(or at least everything but the failed addresses)?
NOTE: I have swift disk caching turned on and most of the memory ~5MB use is in my recipient array.
Code: Select all
using 6528604 memory at mail sent to user2791@localhost...
using 6528904 memory at mail sent to user2792@localhost...
using 6529212 memory at mail sent to user2793@localhost...
using 6529520 memory at mail sent to user2794@localhost...
using 6529812 memory at mail sent to user2795@localhost...
using 6530116 memory at mail sent to user2796@localhost...
using 6530424 memory at mail sent to user2797@localhost...
using 6530724 memory at mail sent to user2798@localhost...
using 6531024 memory at mail sent to user2799@localhost...- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
here is the function called in the foreach loop .
As for logging, I did not turn it on or off, but I did turn disk caching on, assuming that any logging would be dumped to disk. Is this an unreasonable assumption?
Code: Select all
function customize_mail($mail_array , $firstname , $lastname, $email)
{
$i = 0;
while($mail_array[$i])
{
$j = 0;
while($mail_array[$i][$j])
{
$mail_array[$i][$j] = implode("$email" , $mail_array[$i][$j]);
$j = $j + 1;
}
$mail_array[$i] = implode("$lastname", $mail_array[$i]);
$i = $i + 1;
}
return( implode("$firstname", $mail_array));
}As for logging, I did not turn it on or off, but I did turn disk caching on, assuming that any logging would be dumped to disk. Is this an unreasonable assumption?
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
Ok cool, the logger won't be running if it wasn't explicitly turned on so no worries there.
What happens if you remove all that markup you're printing out? Do the values change? Is output buffering turned on (or ob_implicit_flush turned off).
I'll run a similar script myself to see what happens for myself. If you unset() and object, unless there are external references to objects inside it, the inner objects should also unset. unset() is not know for freeing up memory though (you need "null" for that), it simply remove it from scope and allows the grabage collector to deal with it when it sees fit.
What happens if you remove all that markup you're printing out? Do the values change? Is output buffering turned on (or ob_implicit_flush turned off).
I'll run a similar script myself to see what happens for myself. If you unset() and object, unless there are external references to objects inside it, the inner objects should also unset. unset() is not know for freeing up memory though (you need "null" for that), it simply remove it from scope and allows the grabage collector to deal with it when it sees fit.
I took out everything but the memory from the print out, same results at about 300B.What happens if you remove all that markup you're printing out? Do the values change? Is output buffering turned on (or ob_implicit_flush turned off).
Code: Select all
6156544
6156836
6157144
6157460
6157772
6158080
6158416
6158708I have not set output buffering, and I get constant update while the code is running, which suggests no implicit ob_flush.
Now I'm confused, this thread started because unset would not free instances of Swift_Message, I know as I was getting memory overflows as a result, and while I understand that php is a GC language and I can't expect it to clean up in any particular way, it seems to be consistently cleaning up after Swift_Message now, but not after some 300B object or data which I have not yet identified.I'll run a similar script myself to see what happens for myself. If you unset() and object, unless there are external references to objects inside it, the inner objects should also unset. unset() is not know for freeing up memory though (you need "null" for that), it simply remove it from scope and allows the garbage collector to deal with it when it sees fit.
- Chris Corbyn
- Breakbeat Nuttzer
- Posts: 13098
- Joined: Wed Mar 24, 2004 7:57 am
- Location: Melbourne, Australia
Just out of curiosity, what are your readings if you remove all the unset()'s?
And also out of curiosity, what is the imapact if you change:
Code: Select all
unset($part1);
unset($part2);
unset($message);
unset($swift_mail_to);
unset( $body_html);
unset( $body_txt);Code: Select all
//unset($part1);
$part1 = null; //etc etc etcWell I took them out , and nothing changedd11wtq wrote:Just out of curiosity, what are your readings if you remove all the unset()'s?
so now with the svn version, reassigning the object pointer to a new object frees it and GC cleans it up( unlike the last release)
I already inlined the message part constructors, and that had no memory consequences.
Since the leak is 300B, and as the php server times out at 30sec I'll not have enough iterations to reach my memory limit once I properly memory manage the recipient list, but I will have to run the script multiple times (perhaps in multiple ajax calls) to send out large batches. Something is still eating memory, though it is unlikely to hit the 30sec/8MB wall which php sets up and cause the script to abort.
When I finish what I'm working on I'll thrash it around a bit and try to find a minimal control case to see if I can track it down. I only post it here since the only code which might declare/construct things I don't know about is swift, and I like it so much I'd hate to see it leaking.
We are experiencing the same problem (or at least very similar). I haven't got the figures to hand, but I believe we were losing about 280 bytes per iteration. Without having done any real research, my suspicion is that it may be a problem with either Swift_Message or Swift_Address objects not being destoyed correctly.