Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Memory management in pure Actionscript module load and unload  (Read 12239 times)
gregbown
Jr. Member
**
Posts: 16


View Profile Email
« on: July 27, 2009, 02:20:33 »

I have a pure Actionscript project that loads and unloads modules.  Since all the examples that unload modules are MXML based I dont have a clear idea of best practice.
So inside a loaded modules mediator I do this after notifying the shell...
               application.parent.removeChild(application);
               application.dispose();
               this.viewComponent = null;
Inside the shell I clear out any reference to the module and call System.gc();

The memory usage goes up with every module and never comes down so I wanted to get some feedback on what I am doing so far.  The module does not have any proxies but if it did what would be best practice?
In a strictly PureMVC Multicore project I would call removeMediator, removeProxy, pipe.disconnect(),
and junction.removePipe().
Again not sure what to do in my case?  I believe dispose() takes care of the pipes, junctions and core but since I am not handling this with FlexModuleLoader the correct methods are a mixture of what I have seen or adapted from other examples and it isn't working.  I'm not sure how to reference the module from the shell once its loader is cleared out.  I considered keeping the loader in an array to reference by index in the shell then the shell could call removeChild(moduleLoader) instead of the module calling application.parent.removeChild(application).
The current loading method follows Hello Flash method with one slight change.
I store the load index and a unique id in the config object of each module. The shell also maintains a hash map with all current modules index and unique id.

         var content:FlashApplication = moduleLoader.content as FlashApplication;
         var moduleID:Object = new Object();
         moduleID = {(index as Number):unique_id}
         content.router = applicationRouter;
         content.defaultRouteAddress = applicationAddress;
         content.config = moduleID;
                        application.addChild(content);

Any clarity would be appreciated.  Step by step would be awesome.
Thank you

Update
I tried the method I eluded to above and placed the loader in an array. This yielded a minor improvement but I am unable to get closer than 1/2 meg of the original memory usage.


Update#2
     I changed the array to a Dictionary(true) to allow for better cleanup.
     I get the child through a reference with its unique ID, removeChild and then call the
     loader.unloadAndStop(true) then I delete the loader from the loaderDictionary.
     For some reason calling application.dispose() works better when called from the shell on the module?
     If I call it from the module mediator the memory usage is the same as if the module is still loaded.
It looks like so...
            var moduleName:String = getModuleName(moduleID);
            application.removeChild(application.getChildByName(moduleName));
            loaderDict.content.config = null;
            loaderDict.content.fabricator.dispose();
            loaderDict.content.dispose();
            loaderDict.unloadAndStop(true);
            delete(loaderDict);
            startGCCycle(); // Does not make a difference
            sendNotification(CommonConstants.GARBAGE_COLLECTION);

I am able to reduce memory by only .4 meg from its loaded state so...
shell startup = 5.5 meg
load module = 6.4 meg
remove module = 6.0 meg

I hope someone can help me improve on this.

Thank you
« Last Edit: July 29, 2009, 05:53:12 by gregbown » Logged
Tipz
Full Member
***
Posts: 20


View Profile Email
« Reply #1 on: July 29, 2009, 07:41:46 »

Hi mate how do you remove the module.

where do you run these commands from?
the sell or module?
:
application.parent.removeChild(application);
               application.dispose();
               this.viewComponent = null;

And what do you mean by application? The name of the module?

Cheers
Logged
gregbown
Jr. Member
**
Posts: 16


View Profile Email
« Reply #2 on: July 29, 2009, 09:21:29 »

Originally I did that in the module's application mediator however I found I was able to manage memory better if I performed all that in the shell's application mediator by using a unique id reference in the module and storing a reference to each modules loader in a Dictionary with a weak reference(see update#2 in my first post).  I am also on a quest to find the method of removing the core or whatever is left behind when I null everything on the display list and remove all listeners.  Quite frustrating! I still retain approximately two thirds of the loaded state memory usage..
Logged
gregbown
Jr. Member
**
Posts: 16


View Profile Email
« Reply #3 on: August 01, 2009, 08:34:08 »

I found a solution.  I tried removing all the UIComponents and still had the issue with the shell retaining 2/3 of each loaded module. So this led me to believe it is not a UIComponent issue even though the Flex profiler shows a [listener0] as the cause.  I decided to take another look at a similar project (http://www.nutrixinteractive.com/blog/?p=132&cpage=1#comment-30581) claiming to be able to recover all the memory after the first module load, so from the second module on. 

According to Cliff and Adobe "When a module is loaded by the Flex application for the first time, the module’s SWF file is transferred across the network and stored in the browser’s cache. If the Flex application unloads that module, but then later reloads it, there should be less wait time because Flash Player loads the module from the cache rather than across the network.
So, although Flex GC may have released its reference to the loaded module, it will still consume system memory until the browser has flushed its cache. This is seen as a positive thing from a reuse standpoint if you create more instances later, but may not be what you want if you’ve loaded a huge module, only want to use it once and then wish to get rid of it altogether. That might actually require talking to some external JavaScript in the browser to tell it to flush its cache. I don’t even know if that’s possible. But it does explain why sometimes after loading and unloading a module, you still see some memory gone missing."

Any way I digress. The trick is the location of removeChild. I commented out the prior location..

            var moduleName:String = getModuleName(moduleID);
            //application.removeChild(application.getChildByName(moduleName));
            loaderDict.content.fabricator.dispose();
            loaderDict.content.dispose();
            loaderDict.unloadAndStop(true);
            delete(loaderDict);
            startGCCycle();
            application.removeChild(application.getChildByName(moduleName));

And it worked. Before the shell's memory usage would grow after every module load/unload now after the first module it grows by 2/3 and everything else after that is fully recovered. I believe that display objects need to be on stage for the event cycles to run or even be removed properly.

I will try to post my examples soon.
Greg
« Last Edit: August 01, 2009, 08:39:05 by gregbown » Logged
Pages: [1]
Print