Skip Menu |

This queue is for tickets about the XML-RSS-Parser CPAN distribution.

Report information
The Basics
Id: 29299
Status: open
Priority: 0/
Queue: XML-RSS-Parser

People
Owner: Nobody in particular
Requestors: kjellm [...] linpro.no
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Memory leak caused by parent relationships
Date: Tue, 11 Sep 2007 12:37:06 +0200
To: bug-XML-RSS-Parser [...] rt.cpan.org
From: Kjell-Magne Øierud <kjellm [...] linpro.no>
I have found memory leaks in this module. You can use the script included below to verify this. The script uses Devel::Leack::Object to track object creation and destruction. By parsing the same feed several times and for each iteration report tracked objects that still are alive, you can see the object counts go up for each parsing. By also using Devel::Cycle (uncomment the two relevant lines in the script) you can also see that this is caused by cycles in the feed data structure. These cycles are created because each node has a reference to its parent. I have found that by breaking all the parent relationships, the memory leak goes away. My System: * XML-RSS-Parser-4.0 * This is perl, v5.8.8 built for i486-linux-gnu-thread-multi * Linux foo 2.6.20-16-386 #2 Fri Aug 31 00:51:58 UTC 2007 i686 GNU/Linux * Ubuntu/Edgy Regards, Kjell-Magne Øierud ------------------------------------------------------------------------------ #!/usr/bin/perl use warnings; use strict; #use Devel::Cycle; use Devel::Leak::Object 0.90 qw( GLOBAL_bless ); use XML::RSS::Parser; sub delimit { print '-'x78, "\n" } my $raw_feed = join "", (<DATA>); for (1..5) { if ($_ > 1) { delimit(); Devel::Leak::Object::status(); } my $feed = XML::RSS::Parser->new()->parse_string($raw_feed); #find_cycle($feed); } delimit(); __DATA__ <?xml version="1.0"?> <rss version="2.0"> <channel> <title>Foo Bar</title> <link>http://example.com/</link> <description>Foo Bar</description> <language>en-us</language> <item> <title>Lorem ipsum dolor sit amet</title> <link>http://example.com/395852</link> <description> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce non felis in ligula dictum porta. Vestibulum at velit. Donec eros odio, congue in, consequat in, euismod sed, nibh. </description> <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate> </item> <item> <title>Duis vestibulum risus id lorem.</title> <link>http://example.com/395878</link> <description> Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque consequat. </description> <pubDate>Tue, 10 Jun 2003 07:00:00 GMT</pubDate> </item> </channel> </rss> ------------------------------------------------------------------------------
Subject: Re: [rt.cpan.org #29299] Memory leak caused by parent relationships
Date: Tue, 11 Sep 2007 11:42:13 -0400
To: bug-XML-RSS-Parser [...] rt.cpan.org
From: "Timothy Appnel" <me [...] timaoutloud.org>
Thanks for the report. Could you provide a patch of your solution? <tim/>
Subject: Re: [rt.cpan.org #29299] Memory leak caused by parent relationships
Date: Wed, 12 Sep 2007 11:33:42 +0200
To: bug-XML-RSS-Parser [...] rt.cpan.org
From: Kjell-Magne Øierud <kjellm [...] linpro.no>
* Timothy Appnel via RT: Show quoted text
> <URL: http://rt.cpan.org/Ticket/Display.html?id=29299 > > > Thanks for the report. Could you provide a patch of your solution? <tim/>
Sorry, no patch :-/ Only a workaround. I remove all the parents references after I'm done with the feed. This is done by the code included below. It's just a quick hack and nothing I'm particular proud of, but it seems to do the trick. Show quoted text
______________________________________________________________________________ use Scalar::Util qw( blessed ); sub _delete_parents_helper { my $o = shift; if (blessed($o) || ref $o eq 'HASH') { _delete_parents($o); return 1; } return; } sub _delete_parents { my $obj = shift; if (blessed($obj) || ref $obj eq 'HASH') { delete $obj->{parent}; for my $o (values %$obj) { unless (_delete_parents_helper($o)) { if (ref $o eq 'ARRAY') { for my $ao (@$o) { _delete_parents_helper($ao) } } } } } }
______________________________________________________________________________ The best solution would probably be to put calls to Scalar::Util::weaken where the parent links are originally created. I haven't had time to investigate this though. -- Kjell-Magne