Topic: Memory leak in XML parser?

Would someone be kind enough to write a simple widget that parses an XML document repeatedly and see if the chumbyflashplayer.x leaks memory on each iteration?

I'm seeing this on both the Chumby Classic (Flashlite 3.1.5) and on the Chumby One (Flash Lite 3.1.7?).

Re: Memory leak in XML parser?

Hey I am looking for the same. If you get the solution please PM me and share it with me..

Re: Memory leak in XML parser?

I have done that. I have two functions that fetch/parse two different XML files from the web every second.
I've been trying to deallocate memory by setting all function variables to null but that doesn't help much.
The leak is still there.

Any solutions on how to get around this issue?

Re: Memory leak in XML parser?

In our movies, we tend to try to reuse XML objects rather than allocate new ones for each fetch.

For our more sophisticated movies, we use a class called XMLPool that manages a pool of XML objects - other classes check them in and out from the pool.

//
//  XMLPool
//
//  Created by Duane Maxwell on 2009-01-19.
//  Copyright (c) 2009 Chumby Industries, Inc.
//  All rights reserved
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
// 
// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided with the distribution.
// Neither the name of Chumby Industries nor the names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//

class com.chumby.util.XMLPool {
    private static var checkedIn:Array; // of Object
    private static var checkedOut:Array; // of Object
    private static var index:Number;

    private function XMLPool() {}

    private static function assure():Void {
        if (XMLPool.checkedIn==undefined) {
            XMLPool.checkedIn = new Array();
            XMLPool.checkedOut = new Array();
            XMLPool.index = 0;
        }
    }

    //
    // call this to check out an XML object from the pool. It's helpful to provide
    // some textual information about the Object checking it out for leak detection
    // purposes
    //
    static function checkOut(comment:String):XML {
        XMLPool.assure();
        if (comment==undefined) {
            comment = 'anonymous';
        }
        if (XMLPool.checkedIn.length==0) {
            var name:String = '__xml'+XMLPool.index;
            trace('XMLPool.checkOut(): creating new XML object _root.'+name);
            XMLPool.index++;
            var x:XML = new XML();
            _root[name] = x;
            XMLPool.checkedIn.push({name:name,x:x});
        }
        var o:Object = XMLPool.checkedIn.pop();
        if (o.x.xmlDecl != undefined) o.x.xmlDecl = ''; // clear the declaration, if needed. can pile up if set to undefined
        XMLPool.checkedOut.push({comment:comment,name:o.name,x:o.x});
        //trace('XMLPool.checkOut(): checking out _root.'+o.name+' for '+comment+' ('+XMLPool.checkedIn.length+' in, '+XMLPool.checkedOut.length+' out)');
        return o.x;
    }

    //
    // call this function to return a node to the pool
    //
    static function checkIn(x:XML):Void {
        XMLPool.assure();
        var found:Boolean = false;
        for (var i:Number = 0;i<XMLPool.checkedOut.length;i++) {
            var o:Object = XMLPool.checkedOut[i];
            if (o.x==x) {
                XMLPool.checkedOut.splice(i,1);
                delete x.onLoad;
                delete x.onData;
                x.parseXML('<x/>');
                while (x.firstChild!=undefined) { // destroy the child ndes, creating an empty XML object
                    x.firstChild.removeNode();
                }
                x.xmlDecl = undefined; // kill the declaration
                XMLPool.checkedIn.push({name:o.name,x:x});
                found = true;
                trace('XMLPool.checkIn(): checking in _root.'+o.name+' from '+o.comment+' ('+XMLPool.checkedIn.length+' in, '+XMLPool.checkedOut.length+' out)');
                break;
            }
        }
        if (!found) {
            trace('XMLPool.checkIn(): cannot find item '+x);
        }
    }

    //
    // generate a report of the nodes checked in and out of the pool
    //
    static function dump():Void {
        XMLPool.assure();
        trace('XMLPool.dump(): '+XMLPool.checkedIn.length+' checked in, '+XMLPool.checkedOut.length+' checked out');
        trace(' checked in:');
        for (var i:Number=0;i<XMLPool.checkedIn.length;i++) {
            var o:Object = XMLPool.checkedIn[i];
            trace('  '+i+': _root.'+o.name);
        }
        trace(' checked out:');
        for (var i:Number=0;i<XMLPool.checkedOut.length;i++) {
            var o:Object = XMLPool.checkedOut[i];
            trace('  '+i+': _root.'+o.name+' to '+o.comment);
        }
    }
}

To check out an XML object, you'd do:

var myxml:XML = XMLPool.checkOut('fetching weather data');

To check it in, you'd do:

XMLPool.checkIn(myxml);

The pool will create new XML objects if necessary.  The string parameter on the checkOut call is arbitrary - it's used to help identify where a leak might be occurring.

Re: Memory leak in XML parser?

Hello Duane:
Thank you for sharing XMLPool.
I created a new AS2 project in FlashDevelop and this is what I have so far:

/**
 * ...
 * @author
 */
import com.chumby.util.Delegate;
import com.chumby.util.XMLPool;
class Main 
{
    static var app:Main;
    var zip:String;
    var fetchXml:XML;
    
    public static function main(swfRoot:MovieClip):Void 
    {
        // entry point
        app = new Main(swfRoot);
    }
    
    public function Main(root:MovieClip) 
    {
        zip = "04457";
        var refresh = setInterval(Delegate.create(this, getData), 1000);
    }
    
    public function getData():Void
    {
        fetchXml = XMLPool.checkOut("fetching weather data");
        fetchXml.ignoreWhite = true;
        fetchXml.load("http://api.wunderground.com/auto/wui/geo/GeoLookupXML/index.xml?query=" + zip);
        fetchXml.onLoad = Delegate.create(this, fetchDataCallback);
    }
    
    private function fetchDataCallback(success:Boolean):Void
    {
        if (success)
        {
            if (fetchXml.status == 0)
            {
                //trace("got data");
            }
            else
            {
                trace("Problem parsing XML.");
            }
        }
        else
        {
            trace("XML file didn't load.");
        }
        XMLPool.checkIn(fetchXml);
    }
    
}

In the "real" application I will be fetching data from 3 different XML files. From 2 of those I'll be fetching every second.
Despite using the XML Pool the memory leak is still there.
This is what "top" tracked during the first 15 minutes the widget played (in KiloBytes):

4904-5136-5324-5512-5532-5624-5628-5636-5736-5780-5820-5868-6004-6024-6108-6192-6200-6384-6440-6532-6624-6808-6812-6900-6948-7132-7284-7320-7464-7508-7512-7700-7744-7828-8020-8064-8068-8160-8244-8248-8348-8436

And this is what "chumbyflashplayer.x -i myApp.swf" returned:

Adobe FlashLite 3.1.7 Release (Version 9,1,122,0)- Chumby Industries (version 9 build 15-2913 [GCC 4.3.2])
Built for: falconwing; Features: Video ALSA ARM-optimizations
Build time: Tue 02Mar2010 1618
2010-07-30 23:38:38 TRACE: preload.swf v1.02
2010-07-30 23:38:40 SocketObject::Step() socket 19 connect failed, error 111 (Connection refused)
2010-07-30 23:39:11 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:11 ChumbyPipeObject::FindByRequest(102) failed - no find amongst 1 entries!
2010-07-30 23:39:11 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:11 ChumbyPipeObject::FindByRequest(103) failed - no find amongst 1 entries!
2010-07-30 23:39:11 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:11 ChumbyPipeObject::FindByRequest(104) failed - no find amongst 1 entries!
2010-07-30 23:39:11 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:11 ChumbyPipeObject::FindByRequest(105) failed - no find amongst 1 entries!
2010-07-30 23:39:11 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:11 ChumbyPipeObject::FindByRequest(106) failed - no find amongst 1 entries!
2010-07-30 23:39:12 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:12 ChumbyPipeObject::FindByRequest(107) failed - no find amongst 1 entries!
2010-07-30 23:39:12 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:12 ChumbyPipeObject::FindByRequest(108) failed - no find amongst 1 entries!
2010-07-30 23:39:12 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:12 ChumbyPipeObject::FindByRequest(109) failed - no find amongst 1 entries!
2010-07-30 23:39:12 BtPlayObject::StartBtplay() - LaunchDaemon() call response timed out
2010-07-30 23:39:12 ChumbyPipeObject::FindByRequest(110) failed - no find amongst 0 entries!

I've been working on this issue for days and the memory leak still won't disappear.
I don't know what the problem might be.

Any help is much appreciated!!

6 (edited by Ratzfatz 2010-07-31 02:08:57)

Re: Memory leak in XML parser?

Is the pool constantly producing new objects ? If you increase a counter in checkout, decrease in checkIn, does it grow? Could it be, that if an error occurs in fetching the xml-data, only the onData()-function is called, not the onLoad()-method [according to the flash_as2_language_reference.pdf]. Maybe you should try a onData()-function that handles the error and returns the XML-Object to the pool.

Re: Memory leak in XML parser?

What's interesting about the log is that there's a trace() statement in XMLPool.checkOut() function when a new item is created, and another in XMLPool.checkIn() when an item it returned, and neither is showing.

Unless you've commented them out, or are using FlashDevelop with some alternative trace, then it would appear something else is wrong.

Also, I'd try running the widget directly on the device with:

chumbyflashplayer.x -i mywidget.swf -l383

That's a lower-case "L" - it turns on some additional debug information.

Re: Memory leak in XML parser?

Here's another thought - your code is not reentrant.  Look what happens if fetches take longer than a second to complete - the value of "fetchXml" is overwritten by a new one and the old one loses its reference. One of two things might happen - the call might be garbage collected and never complete, or, when it eventually succeeds, it will return the *current* value of fetchXml to the pool, but not get returned to the pool itself - that would be a leak.

Here's what I recommend:

/**
 * ...
 * @author
 */
import com.chumby.util.Delegate;
import com.chumby.util.XMLPool;
class Main 
{
    static var app:Main;
    var zip:String;
    
    public static function main(swfRoot:MovieClip):Void 
    {
        // entry point
        app = new Main(swfRoot);
    }
    
    public function Main(root:MovieClip) 
    {
        zip = "04457";
        var refresh = setInterval(Delegate.create(this, getData), 1000);
    }
    
    public function getData():Void
    {
        var fetchXml:XML = XMLPool.checkOut("fetching weather data");
        fetchXml.ignoreWhite = true;
        fetchXml.load("http://api.wunderground.com/auto/wui/geo/GeoLookupXML/index.xml?query=" + zip);
        fetchXml.onLoad = Delegate.create(this, fetchDataCallback, fetchXml);
    }
    
    private function fetchDataCallback(success:Boolean, fetchXml:XML):Void
    {
        if (success)
        {
            if (fetchXml.status == 0)
            {
                //trace("got data");
            }
            else
            {
                trace("Problem parsing XML.");
            }
        }
        else
        {
            trace("XML file didn't load.");
        }
        XMLPool.checkIn(fetchXml);
    }
    
}

While it looks similar, there is an important change - fetchXML is no longer an instance variable, but rather created per fetch and bound to the Delegate.

Re: Memory leak in XML parser?

Hello Duane:
I just applied the change that you recommended.
This is what I've got so far from chumbyflashplayer.x -i myWidget.swf -l383

Adobe FlashLite 3.1.7 Release (Version 9,1,122,0)- Chumby Industries (version 9 build 15-2913 [GCC 4.3.2])
Built for: falconwing; Features: Video ALSA ARM-optimizations
Build time: Tue 02Mar2010 1618
2010-07-31 13:58:00 New display mask = 017f
2010-07-31 13:58:00 GetRegisteredInstancePid(/var/run/chumbyflashplayer.pid) open failed, errno = 2 (No such file or directory)
2010-07-31 13:58:00 ClientSettings()::Dump
2010-07-31 13:58:00  fileName:                 xmltesting11.swf
2010-07-31 13:58:00  asynchronous load:        f
2010-07-31 13:58:00  memory blocks:            384 (12288 K)
2010-07-31 13:58:00  screen_size:              320X240
2010-07-31 13:58:00  screen_stride:            640
2010-07-31 13:58:00  screen_rotate:            0
2010-07-31 13:58:00  screen_update:            T
2010-07-31 13:58:00  flash_quality:            2
2010-07-31 13:58:00  sound_buffers:            16
2010-07-31 13:58:00  sound_sample_rate:        44100
2010-07-31 13:58:00  sound_channels:           2
2010-07-31 13:58:00  sound_bytes_per_channel:  2
2010-07-31 13:58:00  sound_samples_per_buffer: 8192
2010-07-31 13:58:00  allowCrossdomain:         F
2010-07-31 13:58:00  url_cache_blocks:         4096K
2010-07-31 13:58:00  url_cache_aggression_lvl: 5
2010-07-31 13:58:00  htmlCacheWriteInterval:   60
2010-07-31 13:58:00  htmlCacheStatsFile:       (null)
2010-07-31 13:58:00  maxSecondsRuntime:        86400
2010-07-31 13:58:00  preloadCount:             0
2010-07-31 13:58:00  argument_count:           0
2010-07-31 13:58:00 main() - PATH = /bin:/sbin:/lib:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/bin:/usr/chumby/scripts
2010-07-31 13:58:00 BtPlayObject::OpenPipes() - command input = 0x0020b8b8, output = 8
2010-07-31 13:58:00 BtPlayObject::GlobalInit() - btplay active pid 21774
2010-07-31 13:58:00 SoundObject::GlobalInit()
2010-07-31 13:58:01 FrameBuffer::GetDriverValue(enable) - unable to open /proc/driver/chumbyfwfb/enable r/o
2010-07-31 13:58:01 FrameBuffer::SetDriverValue(enable) - failed to open /proc/driver/chumbyfwfb/enable w/o
2010-07-31 13:58:01 HTTPCurlObject::CurlGlobalInit(/usr/share/certs/curl-ca-bundle.crt,true) - enabling SSL
2010-07-31 13:58:01 MouseWheelObject::GlobalInit() - opened wheel device, handle = 14
2010-07-31 13:58:01 GlobalInit() - input event interface supports relative positioning
2010-07-31 13:58:01 Starting flashplayer, use libcurl = Y, HTTPObject::flags = 9
2010-07-31 13:58:01 HTTPCurlObject::CurlMultiInit() returned handle 0021d7b0, HTTPObject::g_globalOptions=9
2010-07-31 13:58:01 ClientObject::ClientObject(this=0x0021e408) asynch load = n
2010-07-31 13:58:01 ClientObject(1) mmobj=0x4059461c, PlatformPlayer=0x4059d0a0
2010-07-31 13:58:01 ChumbyMem::ctor() using heap memory 0x70c00000 size 2048kB
2010-07-31 13:58:01 ChumbyMem::LinkPrivate(mgr=0021d0a8) previous head is 00000000
2010-07-31 13:58:01 DisplayObject::<ctor>(this=70c00024) UDMA is disabled, falling back to /dev/fb[#]
2010-07-31 13:58:01 FrameBuffer::<constructor>(0,320X240) 640 bytes per line, 153600 == buffer size
2010-07-31 13:58:01 FrameBuffer::AssureFrameBuffer() file for /dev/fb0 is 0x220a78 (fileno 15)
2010-07-31 13:58:01 FrameBuffer::AssureFrameBuffer() m_frame_buffer=0x405fb000
2010-07-31 13:58:01 FrameBuffer::GetFrameBuffer(0, 320X240) - creating new FrameBuffer instance 220a10
2010-07-31 13:58:01 DisplayObject::<ctor>(this=70c00024) got fb=00220a10 for 320X240 idx=0 153600 bytes
2010-07-31 13:58:01 SoundObject::SoundObject[a](0x70c0005c mmobj=0x4059461c): initializing audio, buffers=16, bpb=32768
2010-07-31 13:58:01 SoundObject::Add[a](this=0x70c0005c, mmobj=0x4059461c)
2010-07-31 13:58:01 StreamSoundObject::StreamSoundObject(this=0x70c0005c, mmobj=0x4059461c==0x4059461c): setting up audio
2010-07-31 13:58:01 AssureTouchscreen() - input event interface supports absolute axes
2010-07-31 13:58:01 TouchscreenObject::AssureTouchscreen() /dev/input/by-id/soc-noserial-event-ts fd = 17
2010-07-31 13:58:01 TouchscreenObject::ReadSettings() [5 elements] offsetX:204, scaleX:3790, offsetY:3965, scaleY:-3676, xySwapped:0
2010-07-31 13:58:01 KeyboardObject::<ctor>(this=0x70c0012c mmobj=0x4059461c) next=0x00000000
2010-07-31 13:58:01 ClientObject::Initialize() - successfully set vector font data for 24991 bytes
2010-07-31 13:58:01 chumby/keyboard_object.cpp:1631 - ignoring non-USB joystick soc-noserial-event-joystick
2010-07-31 13:58:01 chumby/keyboard_object.cpp:1643 - unknown event type ts, ignoring
2010-07-31 13:58:01 chumby/keyboard_object.cpp:1598 - ignoring soc-noserial-ts
2010-07-31 13:58:01 ClientObject::Initialize() - keyboard is present
2010-07-31 13:58:01 HTTPCacheObject::<constructor> passing memory block 0x40621008 for 4613734 bytes to cache heap manager
2010-07-31 13:58:01 ChumbyMem::ctor() using heap memory 0x40621008 size 4505kB
2010-07-31 13:58:01 ChumbyMem::LinkPrivate(mgr=002a0d28) previous head is 0021d0a8
2010-07-31 13:58:01 ClientObject::constructor - creating global instance of cache manager 002a0ce8
2010-07-31 13:58:01 ClientObject::SWFValidateCommon(url=file:////mnt/usb-AF70-9183/xmltesting11.swf,size=2697) validate result 1
2010-07-31 13:58:01 ClientObject::Initialize() - preloading 1 class libraries
2010-07-31 13:58:01 TRACE: preload.swf v1.02
2010-07-31 13:58:01 ClientObject::Initialize() successfully loaded 1 preinstalled libraries
2010-07-31 13:58:01 SensorObject::SensorObject() g_bend_device 0x2a0d58
2010-07-31 13:58:01 ClientObject::MainLoop() - masterInstance step time = 0, frame interval = 83
2010-07-31 13:58:01 BtPlayObject::Pump(cycle 0) got response OK 1000 flashplayer startup

2010-07-31 13:58:01 BtPlayObject::Pump(cycle 0) got response OK 1001 option songloop 1

2010-07-31 13:58:01 BtPlayDeferredAction::Execute(chkr) - got response 1001
2010-07-31 13:58:01 BtPlayDeferredAction::Execute(chkr) - got response 1000
2010-07-31 13:58:01 BtPlayObject::Pump(cycle 0) got 2 responses, executed 2 deferred actions
2010-07-31 13:58:01 ChumbyPipeObject::ProcessLine() got chumbpipe pid = 22472
2010-07-31 13:58:01 ClientObject::DoTimeCheck() elapsed time = 1280599081s now=1280599081 next check=1280599200
2010-07-31 13:58:01 si_object.cpp:assureTimeZoneOffset(): changed offset from 0 to -14400000, zone=EDT offset=-14400 dst=1
2010-07-31 13:58:01 MemoryStateMonitor::Check() - MemFree=24096kb, Cached=14096kb, Buffers=3724kb, total=41916kb - above danger zone by 29628kb
2010-07-31 13:58:02 SI_Object::SI_OpenSocket(0x4059461c)
2010-07-31 13:58:02 NetStreamRequest::Open(2): Opening protocol 'http://' host 'api.wunderground.com' port 80 location '/auto/wui/geo/GeoLookupXML/index.xml?query=04457'
2010-07-31 13:58:02 NetStreamRequest::Open(2) opened http object id 1
2010-07-31 13:58:02 SocketObject::Step() waiting for connection start time 51840218
2010-07-31 13:58:02 ClientObject::HeartBeat(51840229) elapsed 15.085s prev high 0.000s
2010-07-31 13:58:02 ClientObject::HeartBeat() player running 2s (3014368216)
2010-07-31 13:58:02 SocketObject::Step() socket 21 connect failed, error 111 (Connection refused)
2010-07-31 13:58:03 NetStreamRequest::ProcessHeaders(2) content-type: text/xml
2010-07-31 13:58:03 NetStreamRequest::Step(2) done, closing stream (7361 of 0 bytes, avail=0) status=200 (ok)
2010-07-31 13:58:03 NetStreamRequest::Open(3): Opening protocol 'http://' host 'api.wunderground.com' port 80 location '/auto/wui/geo/GeoLookupXML/index.xml?query=04457'
2010-07-31 13:58:03 NetStreamRequest::Open(3) opened http object id 2
2010-07-31 13:58:03 NetStreamRequest::ProcessHeaders(3) content-type: text/xml
2010-07-31 13:58:03 NetStreamRequest::Step(3) done, closing stream (7361 of 7361 bytes, avail=0) status=0 (ok)
2010-07-31 13:58:04 NetStreamRequest::Open(4): Opening protocol 'http://' host 'api.wunderground.com' port 80 location '/auto/wui/geo/GeoLookupXML/index.xml?query=04457'
2010-07-31 13:58:04 NetStreamRequest::Open(4) opened http object id 3
2010-07-31 13:58:04 NetStreamRequest::ProcessHeaders(4) content-type: text/xml
2010-07-31 13:58:04 NetStreamRequest::Step(4) done, closing stream (7361 of 7361 bytes, avail=0) status=0 (ok)
2010-07-31 13:58:05 NetStreamRequest::Open(5): Opening protocol 'http://' host 'api.wunderground.com' port 80 location '/auto/wui/geo/GeoLookupXML/index.xml?query=04457'
2010-07-31 13:58:05 NetStreamRequest::Open(5) opened http object id 4
2010-07-31 13:58:05 NetStreamRequest::ProcessHeaders(5) content-type: text/xml
2010-07-31 13:58:05 NetStreamRequest::Step(5) done, closing stream (7361 of 7361 bytes, avail=0) status=0 (ok)

The last NetStreamRequest statements repeat every time there is a fetch.

I compared my log with that of RapidFire
(a Weather Underground SWF  that fetches weather data every 2 seconds -- stable, no memory leaks detected).

I see two peculiar things:
1. My Log doesn't have a Open(1) request -- Rapidfire does.
2. In my log, the statement "NetStreamRequest::Open(5) opened http object id 4", the open parameter and the object id are off sync, RapidFire has them in sync all the time.

The RapidFire memory usage increases by 4 KB during the first 150 requests (1 request per 2 seconds) and than it stabilizes. On the other hand my application's memory usage it will increase with 24, 60 or even 100 KB.

As for FlashDevelop, i think it uses a different type of trace.
This is what it is now tracing (the source code is the same as you suggested):

Running process: C:\Program Files\FlashDevelop\Tools\fdbuild\fdbuild.exe "D:\workspace\flashdevelop\xmltesting\xmltesting.as2proj" -ipc 99027490-cc0b-45f0-98b0-a293f63fc418 -compiler "C:\Program Files\FlashDevelop\Tools\mtasc" -library "C:\Program Files\FlashDevelop\Library"
Building xmltesting
Build succeeded
Done(0)
~/com/chumby/util/XMLPool.as:52:XMLPool.checkOut(): creating new XML object _root.__xml0
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)
~/com/chumby/util/XMLPool.as:84:XMLPool.checkIn(): checking in _root.__xml0 from fetching weather data (1 in, 0 out)

It seems to me that XMLPool is working correctly, however the memory leak is still there.

Re: Memory leak in XML parser?

Can you try one more thing for me?

Change:

        fetchXml.onLoad = Delegate.create(this, fetchDataCallback);

to:

    Object(fetchXML).__target = this;
    fetchXml.onLoad = function(success) {
        this.__target.fetchDataCallback(success,this);
    }

Let's see if that has some effect.

Re: Memory leak in XML parser?

I just tried that Duane.
The leak is still there. Memory used increased by ~4000 KB in 15 minutes.
I'm starting to wonder if this issue might be related to FlashDevelop and to the MTASC compiler somehow.

Re: Memory leak in XML parser?

Yeah, I'm a bit worried about the trace stuff - maybe it's piling up somewhere.  There's a setting in Flash Develop to use the standard Flash trace() functionality rather than the normal one used for desktop debugging.

Re: Memory leak in XML parser?

Duane:

I think the trace function might be the issue.
I tried commenting out all the traces from the Main, Delegate and XMLPool classes and the application seemed to be stable.

I found out that another way to get rid of the traces in FlashDevelop is to build the SWF in "Release" mode.
They claim that the difference between the "release" and "debug" mode is that the former produces a "smaller and faster" SWF -- it also seems to be able to fix the memory leak as well.

What I think is going on is that when an application is built in "release" mode, FlashDevelop will do some optimizations and one of them involves getting rid of all the trace() statements...and that indirectly fixes the memory leak.

I had it running for 6.5 hours last night and everything seemed to be ok.
I'll try to incorporate your suggestions into the real application that I'm building - hope that will go well.

Thank you for all your help!