Good Memory Management When Using PureMVC

Preface

There are a lot of good articles already written & screen casts about memory management in Flash Player.  I encourage you to read them first before reading the below.  I cover memory management in a large application using a PureMVC architecture, typically on top of Flex.

Introduction

Memory Management, referring to making sure your application doesn’t leak memory through the use of responsible coding practices, is hard.  It’s even harder if you don’t have a history of having to deal with such things (*cough* Flash Developers *cough*).  It was challenging for me to learn… and I’m still learning.  As the Flex community has grown, we’ve seen the influx of more traditional programmers to help write blog entries and white papers, especially for AIR apps, on better memory management, how to prevent memory leaks, and how memory in the Flash Player works (and doesn’t work).

What I haven’t seen is this applied to Enterprise programming and frameworks.  Most articles are either from a Flash game developer, or a Flex dev referring to AIR applications.  From my consulting, the people who need the biggest help are doing the web applications that need to run as long as a normal desktop application.  Below, I’ve documented how you do this using PureMVC.

Why Memory Management?

Many Flex & Flash projects don’t need to use good memory techniques.  Memory leaks on a small scale are ok.  If the application is responsive to the user, you have no problem.  The purists will argue that creating a bunch of things and not removing them from RAM is bad.  However, if your application works, is responsive to the user, and doesn’t adversely affect other applications, then the purist is wrong.

For things like games that use a lot of system resources, or applications that need to run on your computer longer than 10 minutes, memory leaks will eventually use all available memory that a SWF is allowed, and cause it to stop working, or the browser to crash.  The application will be slow to respond, Garbage Collection may freeze Flash Player while it attempts to clean up, and/or your memory will become fragmented over time.  Fragmented memory makes things slower to access it, and thus can slow down your application.

Another side effect of not cleaning up the memory you’ve used yet no longer need is weird bugs.  You’ll sometimes have objects around that are doing things, yet you have no strong-references to.  Examples include timers still running, service classes that were “removed” yet receive a response from the server and no one is still listening for the response, or duplicate PureMVC classes.  Weird bugs can arise from these situations, causing your debugging time for problems to take longer.

Bottom line: If you want  your application to run for hours at a time, not to adversely affect other applications, and remain responsive, you need to employ good memory management.

Smaller projects that have memory leaks can often be re-factored.  Enterprise ones, however, will often take months to fix.  Worse, those months will have a major lack of visible project progress as things are broken on purpose to get things back into shape.  This is sometimes a contributor to the reason larger projects have the infamous “last 10% is 90% of the work”.  If you don’t start early with easy to follow conventions, it’ll be really hard to add them in later in; “add” is too nice a word since those projects don’t just stop to wait for you to clean up some memory; the logistics are a lot more complex than that.

This is even worse in Agile.  Where 80% of your time is re-factoring and you’re constantly creating new code, it’s quite challenging to keep up.  The best you can do is have a good understanding of the life cycle of your app.  The better understanding you have, the better you’ll be able to know what you don’t have to clean up, and what you do; i.e. when you have to write code and when you don’t.  Remember, designers / UX people can help here.  They’ll be able to give you a better understand of user paths into your app, and you can focus on what truly matters and knowingly let the rest remain in memory.

Example: If the user is constantly creating 3 types of forms, you can focus your efforts on ensuring they are cleaned up.  If the user hardly ever goes to a FAQ page, you can spend little to no time ensuring it’s cleaned up.  The reverse can be true as well.  If the 3 forms are accessed often, you can ensure that only the data they create is unique, but the forms themselves remain in RAM.  You can instead focus your efforts on those items that are rarely accessed.  If you user does go to the FAQ page, they shouldn’t be punished when they leave; it should remove from memory.

Why NOT memory management?

Memory management, sadly, requires you to often write more code.  More code is a negative contributor to projects.  For Enterprise code bases, they are often quite large.  Even when all features are completed, you are often adding more code for modifying features, or fixing bugs.  The last thing you want to do is knowingly add more code if you can help it.

A common practice for classes is to add destructor methods.  These are basically methods that are called “public function destroy():void” and clean up the class.  It’ll remove strong event listeners, remove child display objects, and stop asynchronous classes such as Timers, Sockets, and service classes.  Another common practice is to create “addListeners” and “removeListeners” functions that will do just that; add event listeners to an object/objects, and remove them.

Often, though, both classes fall into the trap of those methods never staying in sync with the rest of the class.  If you create a new object, you forget to clean it up in destroy.  That, or you add a new event listener amongst the other 4, but forget to add it to the removeListeners function.  Worse, and most often the case, these methods aren’t ever called.

The developer meant well, but ended up creating more code, code that isn’t used, and code that isn’t even finished with no obvious indications thereof.  The road to hell is paved with good intentions.

When View’s Go Away

When creating applications, whether Flash or Flex, you’ll have View’s that are shown and hidden.  You’ll have to make the decision how they are hidden.  If you need the View quickly, you’ll set visible to false and true.  If you don’t need to View quickly, you’ll simply addChild/removeChild.  If you only need the View rarely, you can destroy it entirely and rebuild it when you need it.

When you know you need to destroy a View, then you can write code to remove it from memory.  This is the only YAGNI approach I’ve found that works.  Meaning, as soon as you recognize you’ll need to remove a View, only then do you write code to clean up the mess.  If you do it prematurely, you just wrote a bunch of code you may never need, and now have to maintain.  Adding it later actually isn’t so bad, but that assumed you designed for it.  Meaning, if you don’t make it easy to remove a View, it’ll be hard because you first have to re-factor the code that uses it.

From a GUI perspective, this is sometimes ok.  Take the case of a View used in a Flex ViewStack.  All a ViewStack does when you leave a View is remove the View from the DisplayList.  If she’s a big View, that’s nice… but not enough.  You’ll need to refactor this code to support the child in the ViewStack from being destroyed.  You can either wrap the View you want destroyed in say, a Canvas that has code to destroy/create the single child View based on Event.ADDED/Event.REMOVED.  That, or you could make the child a ModuleLoader, and based on Event.ADDED/Event.REMOVED, load/unload the module.  Or, you could just write a function that creates/destroys views based on where it’s supposed to go.  You lose the flexibility & ease of using a ViewStack, but you get more control with more efficient code.

Registering & Unregistering View’s in PureMVC

…but this assumes you can, in fact, get the View out of memory.  In the case of frameworks, larger Views will often use the Presentation pattern, a Mediator, or something like it.  Sometimes it’s directly in the View itself.  How ever it’s done, the “Master View” will integrate with a framework.  In PureMVC, this is usually via registering itself with PureMVC.  There are varying ways to do this.  The way I do it is via ApplicationFacade.getInstance().registerMyView(this), where “this” is the instance reference passed in.  The ApplicationFacade will take the instance, create & register a Mediator passing the instance into the constructor of the Mediator.

public function registerMyView(view:MyView):void
{
        facade.registerMediator(new MyViewMediator(view));
}

Others will dispatch an event, and have a Command class handle those details to prevent their ApplicationFacade from growing large.  Either way, time and time again, I see View’s that should be removed, but have no “unregister” function, nor a Command to remove the Mediator.  Basically, there is a lot of code to register the View the the framework and create associated Application domain classes, but nothing to clean up everything when you’re done with it.

The way I do it is via ApplicationFacade.getInstance().unregisterMyView(this).  This is the opposite of the last method; it’ll unregister the Mediator.  The Mediator’s onRemove function will fire, which gives the Mediator an opportunity to clean itself up.

public function unregisterMyView():void
{
        facade.removeMediator(MyViewMediator.NAME);
}

Weak vs. Strong Listeners

Let me take this opportunity to protest against using weak listeners.  They are for pussies.  Seriously, the only time they are valid is when you are creating code modules that other developers could use, and there is no conventional destruction point.  Since you have no control over when your code will have the opportunity to clean itself up, nor do you know if the developer using your code is smart enough to call your destroy method, you try to code as defensively as possible.  If you must snag a reference to a global object such as “stage” for example, which’ll surely lock your code into memory, you at least make it a weak listener AS WELL AS listening for Event.REMOVED_FROM_STAGE.

It’s been suggested to always use weak listeners when using Timers for example.  Since these are some the major culprits of memory leaks in applications, if you use a weak listener, you’re set right?  Same with Dictionaries with weak keys, right?  *face palm*  Sure man… with that attitude, I’m sure you’re code REALLY makes an effort to help clean itself up.  Besides, Flash Player 9 has some issues garbage collecting weak listeners, so you can’t even depend on it working as advertised.  They’ve fixed a lot of this in 10, but you need to make an effort to de-allocate as much memory as you can.  Just because a large object has no references to itself doesn’t mean the Garbage Collector will immediately free up everything.  While it is a black box, you do have ways of helping it out.  In my experience, it’s more likely to free up smaller objects more often than large objects since running Garbage Collection itself is a processor intensive operation.

If your code is explicit, it’s clear where you’re freeing memory.  If you’re not, it’s challenging to figure out where leaks occur, nor is it easy to write proactive code to free up memory.  Granted, deadlines may dictate otherwise, and I concede the point on those instances.  Regardless, a lot of people who use weak references for listeners forget that unless they keep a reference to the object itself, it’ll randomly get garbage collected, which leads to strange bugs for asynchronous classes that are hard to reproduce reliably.  If you don’t know what you’re doing or have doubt, just use a strong reference and provide a clear way of removing it later.

Any help you can provide… would be… well… helpful!

Make no mistake: Helping the Flash Player garbage collect your objects has major, positive impacts.  Even a half-assed approach is better than none.

Let’s take an Array or ArrayCollection full of Strings for example.  He’s within a View, and you removeChild the View, and null the reference in his parent.  The GC will eat it eventually right?  Wrong… you accidentally have a stage listener buried deep within the bowels of a base class of a Button you’ve written.  If that’s all you’ve done, simply removing the child from the DisplayList and nulling the reference, you’ve at least giving back memory the View was using to display itself to the screen.  Glass half full baby!

Taking it a step farther, what if you’re View implemented a destroy method, and cleaned up its internals to help the GC out, and free up some memory of things it’s no longer using?  Remember, the View itself is still locked in RAM because you don’t yet know about the rogue stage listener.  BUT, you at least remove all Strings in the ArrayCollection and null its reference in your destroy method.  Running the Flex profiler, you’ll see some [reap] and [sweep] using more CPU time + memory go down slightly + less String instances.  Yum yum… while your View couldn’t get it’s fat arse outta RAM, you at least managed to free up all of those Strings it had a reference too.  They no longer have any references to them, and therefore they are cleaned up, and the memory THEY use is freed up.  Rad!  GLASS HALF FULL BABY!  Even with a memory leak, we’re lessening the damage by freeing as much memory as we can.

I know this doesn’t fix the problem, but if you’re under a deadline you gotta do what you can to survive.  The only reason I don’t think weak listeners are justified in the deadline scenario is because it’s like you’re not even trying to do the above: thinking about what View’s & classes need to be removed, writing destructor methods, and validating they worked.  Sometimes you just don’t have time to do those things, though…

What do you do in a Mediator::onRemove method?

Assuming you’re PureMVC is setup correctly, then the onRemove function of your Mediator’s will fire when it’s removed from the PureMVC ApplicationFacade.  Here, you can remove strong event listeners you’ve made on the View, remove the Mediator’s view reference by setting it to null, and clearing any other data.  This is where things get hard.

Removing the View’s listeners and it’s reference is easy; there is a 1 to 1 relationship with with Mediator’s and a View.  But what about Commands and Proxies?  If the Mediator registered one or more Commands, it’s pretty clear he should unregister them.  Often I’ve seen Commands that are relevant to a particular View being registered in the ApplicationFacade by overriding the initializeController method.  For smaller applications this is ok.  For larger ones, it’s still ok in that they don’t necessarily take a lot of RAM.  The problem is this doesn’t scale.  Your Facade will get really really large.  Some people compensate for this by creating multiple Facades for the relevant Application Domain (called Contexts in early RobotLegs builds).  While this spreads the damage, it removes relevance from the code; it isn’t immediately obvious what problem domain these Commands are associated with.  When the Mediator registers them, it’s usually pretty obvious.  That, and it makes it easier to remove them with confidence without worrying about breaking things.

…Proxies, however, are another story.  Proxies are the #1 cause of race conditions in PureMVC.  Regardless of how they are written (holders of data as your Model or Services or both), they are often encapsulated enough that they could be relevant to many different Views, and thus many different Mediators.  This causes a problem in knowing when they should die… if ever.  The benefits of using a stateful client like Flash Player RIA’s, as opposed to a paged based, non-AJAX HTML application, is that you get the benefits of keeping data in RAM.  This in-RAM data allows the application to be quick and responsive.  As long as your data is ActionScript objects (excluding XML, Strings, Bitmaps, and large ByteArrays) your memory usage is often very low.

Therefore, there isn’t a lot of harm leaving Proxies around.  The one side effect is when your profiling your application via System.totalMemory, you’ll notice it doesn’t go down as much when you’re View is destroyed.  Using the Flex profiler, when taking memory snapshots, you’ll notice you’ll have a lot of potential loitering objects (things that are still around in memory even after your View is destroyed and Garbage Collection has run).  If you’re trying to track down a leak, some of those loitering objects, your Proxy and his data, are valid… you want them to loiter in the first place so you can immediately access them again later.  Additionally, you’ll need to write more defensive & proactive code in your PureMVC code that accesses the Proxy.  For example, instead of registering the Proxy every time, you need to ensure it’s not already registered.

private function getSearchProxy():SearchProxy
{
        var searchProxy:SearchProxy;
        if(facade.hasProxy(SearchProxy.NAME))
        {
                searchProxy = facade.retrieveProxy(SearchProxy.NAME) as SearchProxy;
        }
        else
        {
                searchProxy = new SearchProxy();
                facade.registerProxy(searchProxy);
        }
        return searchProxy;
}

Another tactic if the amount of data a Proxy has uses a lot of memory, or you just need every byte you can, is to cache on the local machine.  If you’re running in a web browser, you can use a local SharedObject and save your serialized data.  If you’re using AIR, you can read from the local disk via File, or use the local SQL database support. When the Proxy is re-created, he can check the local cache first, validate the data is good, and use it instead of fetching it again from the back-end.

Bottom line, if you DO remove a Proxy, that’s your cue to go implement his onRemove method as well.  Here’s an example of a Mediator cleaning up its View reference & listeners as well as proxies.

protected override function onRemove():void
{
        if(community)
        {
                community.removeEventListener(LoginEvent.LOGIN, onLogin);
                community.removeEventListener(LoginEvent.LOGOUT, onLogout);
                community.removeEventListener(LoginEvent.CHANGE_PASSWORD, onChangePassword);
                community.removeEventListener(SearchEvent.SEARCH, onSearch);
                community.removeEventListener(PowerEvent.OPEN_POWER, onOpenPower);
                community.removeEventListener(PowerEvent.DELETE_SEARCH_POWER, onDeletePower);
                community = null;
        }

        facade.removeProxy(AuthenticationProxy.NAME);
        facade.removeProxy(SearchProxy.NAME);
        facade.removeProxy(GetPowerProxy.NAME);

        sendNotification(ApplicationFacade.COMMUNITY_SHUTDOWN);
}

And here’s an example of a SearchProxy nulling out internal data, an ArrayCollection and a String, as well as cleaning up an internal web service.

protected override function onRemove():void
{
        powers 		= null;
        _searchText = null;

        if(searchPowersByNameService)
        {
                searchPowersByNameService.removeEventListener(CommunityServiceEvent.SEARCH_POWERS_BY_NAME_ERROR, onSearchPowersByNameError);
                searchPowersByNameService.removeEventListener(CommunityServiceEvent.SEARCH_POWERS_BY_NAME_SUCCESS, onSearchPowersByNameSuccess);
                searchPowersByNameService = null;
        }
}

Remember, once you start implementing clean up methods, you’ll need to keep them in sync with any changes in the class.  Tread with confidence.

Conclusions

Managing memory in Flash & Flex applications is hard.  Validating your hard work actually is paying off is time consuming.  Most programmers who are used to managing memory keep it in the forefront of their minds while their coding, so they often don’t perceive it as an issue/challenge.  A lot of times the frameworks we use handle a lot of the mundane details of these operations for us (like Tweening engines).

If you’re application does need to run for any long length of time and you’re using PureMVC, having a good, up front understanding of what Views need to stick around and which ones don’t will help you better plan for which Views, Mediators, and Proxies you’ll need to write code for to free up memory.  If you do your best to make each View follow it’s own Application Domain problem it’s solving for, then it’s easier to have that entire silo follow the standard removal scenarios, and thus code to it.

For example, if you are creating a FAQ View, and it has a FAQ Mediator with a FAQ Proxy, then it’s pretty simple to clean up thing when you’re done: implement a destroy method in your View, then implement onRemove methods in your Mediator and Proxy.  When in doubt about the Proxies, just keep ’em around since they usually aren’t the biggest memory offenders… but be sure to validate this using the Flex Profiler and/or System.totalMemory as even rogue XML can take 200 megs or more.  It’s easier to make View’s more efficient than it is to solve for race conditions in PureMVC.

A good tool to help visualize your memory usage in real-time is Mr. Doob’s “Stats”.  Just be sure your system is only running 1 SWF at a time as System.totalMemory, what Stats uses, applies to all SWFs running on your box.  I usually wrap him with a UIComponent, add a right click menu to my app to open him via ContextMenu, and launch him via PopUpManager.  Another tool you can use is Flex PMD.  It’ll help identify which code isn’t used… and perhaps should, like destroy methods that aren’t ever called.  Finally, if you’re desperate on Flash Player 9, you can also force Garbage Collection via the LocalConnection hack.  This saved us on a project where we were loading SWF’s.

Remember, if you destroy & recreate a View and his PureMVC equivalent classes a lot, you may fragment the memory over time, so don’t get overzealous.  Use your best judgement, and don’t be afraid to get the designers help on which sections of the app need to be the most responsive, and which ones it’s ok to lazy load.

12 Replies to “Good Memory Management When Using PureMVC”

  1. Great post Jesse. You hit the key points on memory management and GC. Could not agree more on the weak listeners. Don’t wait for someone else to pick up your garbage, do it yourself.

  2. Event.REMOVED_FROM_STAGE has given me serious headaches in the past as Flex likes to reparent objects. It has lead to “why the f isn’t my view being mediated anymore?” scenarios, or worse it calls the destroy “randomly”

    People seem to love using weak listeners and anonymous functions on Timers. This is *bad*. Don’t use weak listeners on anonymous functions

    Using a Command is a great place to map Mediator/View specific commands. It isolates the tier where you do your registering/mapping, and providing a subsequent cleanup command that is fired up when the mediator/view is removed is effective also. I really dislike doing any registering/mapping in the initialize of the ApplicationFacade, and think all of this work is better suited to a command. Nothing wrong with putting this into a mediator either, just depends on the granularity of control you want/need in an application. I like to keep the single responsibility principle in play as much as possible.

  3. Just wondering what the benefit is of writing:

    ApplicationFacade.getInstance().registerMyView(this);

    to:

    facade.registerMediator(new MyViewMediator(new MyView()));

    This would only work for registering Mediators of the same type. Surely you don’t create a custom register method for every Mediator type in your application? Just curious ;)

  4. @Will 2 things. First, I don’t use PureMVC anymore, I’m a fan of RobotLegs.

    Secondly, yes, I do do it that way. I’ve only had to register multiple same type Mediators in one AIR project. That was the exception to the rule. PureMVC out of the box doesn’t support this anyway because all the Mediator’s have to have different names so clearly Cliff didn’t think this would be a common practice. That said, people like Joel Hooks have stated to DO do this often… :: shrugs ::

    Either way, yeah, my ApplicationMediators do get kind of big, but the easy way to fix is just refactor into multiple Facade’s that reside in their respective domain. You have to do this anyway if you’re creating modules, or just generally large projects. Loading everything up front, while easier to read, makes it hard to scale and unload parts from memory. If you load all Mediators once, for example in your Facade, then you have to write code elsewhere to re-register it.

    Additionally, those 2 lines of code allow a clean separation in a View. If you need to test a View in isolation because someting funky is going on, you can just comment out those 2 lines of code, and the View no longer has dependencies on the framework. In large applications, this is a must. Otherwise, solving GUI related bugs takes a loooooong time.

    …for smaller projects, no, I register everything up front.

  5. Jesse,

    Good article, albeit very long-winded!

    I’ve found that while trying to keep code D.R.Y., and particularly when utilizing a multi-core application, doing something like ApplicationFacade.getInstance() can cause issues. Primarily because of the direct dependence of a singular(not in just pattern, but in purpose) ApplicationFacade (which in a multi-core app is never the case), and a RTE regarding casting. Because of this, my mediators typically have a reference back to the Facade that is critical to remove the references to.

    I typically use weak listeners anyway, often removing when I’m no longer needing them. The best example I can think of is a popup that plays a playlist of audio (such as composite instructional audio), but the user has the opportunity to close the window at any time. To avoid having to write the destroying of the event listener, I rely on the weak listener… Is this bad practice? I’ve yet to see a leak in this regard, but have come across others that I haven’t been able to identify yet (specifically speaking, loading a semi-to-complex SWF created in Flash).

  6. @KillerSpaz Sorry chief, brevity is a skill I currently do not possess. Twitter is helping.

    That said, it’s a complex topic, and I’d rather defer on the side of assuming the user needs all the possible details for this complex subject.

    First off, mad props you actually successfully implemented multi-core. Most complicated shiz I’ve ever seen in my life.

    Second, Mediator’s already have a reference to facade built in, so not sure I get what you mean about reference back to the Facade.

    Third, that’s my point; avoiding writing clean up code, and instead just using a weak reference is easier to get away with now than it was back in Flash Player 9. That said, there is still many other things to clean up often, not just listeners, hence if you’re going to clean up other stuff, you might as well clean up listeners. However, using weak listeners that you later plan to clean up is fine; I don’t see the harm there; it’s just the intent makes no sense. If you’re going to use a weak listener as well as listening for the PopUp’s CloseEvent.CLOSE in order to write clean-up code… don’t use a weak listener. People reading the code will get confused.

  7. in regards to weak references it is worth mentioning 2 important things:

    1) weak references are more expensive then strong. they take longer to process.

    2) you never know when a weak reference will get garbage collected.

    Now if my team is working on a project that WE built. Then yeah: RCOK DESTORY. But if we jump into the middle of a project we didn’t build where we could miss a destory or dont have time to crawl through all their code to add it then using weak references may not be a bad idea imo.

    -erik

  8. Great article. The way Flash’s addEventListener() defaults to strong actually helps save typing on that line of code anyway.

    I do think a decent compromise is to recognize which elements of a project are really worth the extra effort. If you’re making a billion instances of something then it’s time to do the necessary work. If there’s a part that never or rarely needs to get totally removed I suppose you can use weak references or–gasp–just let the memory leak go. I’m not suggesting people become “pussies” but step 1 is to notice when it matters most.

  9. Hi Jesse,

    Search This in google–
    what are the advantages of using weakreferences in Flex

    This page link comes 2nd But the title i am getting is reeducate the great efforts done by you for this article , Just a suggestion Try to solve it :)

Comments are closed.