LukeyBoy has asked for the wisdom of the Perl Monks concerning the following question:
The kicker comes when I'm exporting and importing the user's data - I use XML::Writer to output the data, and I export the bookmarks and cache objects into an XML file. The cached objects are encoded using MIME::Base64. Exporting works like a charm...
The problem is when importing data. Perl runs out of memory! I have an XML::Parser object created with appropriate handlers that branch depending on the element type. The export format contains three main elements - "post", "object" and "relationship". (A relationship is a link between two objects). So on import, relationships and posts import fine but Perl has the memory issues when reading and decoding the Base64 encoded objects.
The XML::Parser fires events into my "Char" handler, where I append the characters in the current element to a scalar...
$parser->setHandlers(Char => sub { my $expat = shift; $ocontent = $ocontent . shift; }...
The $ocontent scalar is defined in the scope of the function that instantiates and starts the parse. So I build up the $ocontent with the encoded data and then finally I call decode on it and import it into the user's database. That works well for somewhere around two hundred objects, at which point Perl freaks out trying to map and unmap memory (according to strace) and stalls at full CPU usage. When I comment out the "$ocontent = $ocontent . shift;" line, I don't run out of memory. And I tried setting the ocontent variable once, thinking that maybe the Base64 decode method or the MySQL DBI methods were causing the error - so in that test I used the same chunk of data for all objects, and I did not run out of memory.
So all signs point to my character buffer causing a memory leak. Does anyone know how to fix or workaround this? (Also you can look right at the CVS tree of my project if it helps).
Update: I figured it out! After appending the characters from XML::Parser to my string I now undef the expat character variable. Suddenly the whole script moves way faster and uses less memory. This is the new character data handling routine:
Char => sub { my $expat = shift; my $chars = shift; $cbuffer = $cbuffer . $chars; undef $chars; }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Out of memory with XML::Parser
by runrig (Abbot) on Sep 14, 2005 at 17:39 UTC | |
by LukeyBoy (Friar) on Sep 14, 2005 at 17:45 UTC | |
by LukeyBoy (Friar) on Sep 14, 2005 at 18:41 UTC | |
by runrig (Abbot) on Sep 14, 2005 at 19:00 UTC | |
by runrig (Abbot) on Sep 14, 2005 at 18:49 UTC | |
by LukeyBoy (Friar) on Sep 14, 2005 at 20:41 UTC | |
|
Re: Out of memory with XML::Parser
by mirod (Canon) on Sep 14, 2005 at 19:49 UTC | |
by LukeyBoy (Friar) on Sep 14, 2005 at 20:36 UTC | |
by mirod (Canon) on Sep 14, 2005 at 20:43 UTC | |
by LukeyBoy (Friar) on Sep 14, 2005 at 20:58 UTC | |
by mirod (Canon) on Sep 14, 2005 at 21:45 UTC | |
|