Plugging Video & Image Memory Leaks in Adobe Air

Adobe AIR is known for memory leak issues, especially in regards to loading and unloading video. I have seen applications with alternating video and images crash unexpectedly after running for only 20 minutes with no user input. After doing some investigating on my own, I can confirm what others have said in the past: You have to take extra steps when unloading a video or image, or risk a serious memory leak.

Removing Images: Clear the “source” attribute
Let’s say you want to unload a set of images from display object myContainer. The obvious solution would be to myContainer.removeAllChildren(), but unfortunately, this is not enough to recover the memory for the images. To truly recover the memory, you need to call:

for each (var child:DisplayObject in myContainer.getChildren()) {
   if(child is Image) {
      (child as Image).source = "";
   }
}
myContainer.removeAllChildren();

My thanks to Russell Brown for this non-trivial solution. I can confirm his results; implementing this solution significantly reduces memory leakage.

Removing Movies: Close the movie
Next, let’s say you want to unload a movie. Most people would just stop the video and remove it from the screen but like the issue with images, this is not enough. Developers should use the following code to properly unload a movie and recover the memory:

for each (var child:DisplayObject in myContainer.getChildren()) {
   if(child is VideoDisplay) {
      (child as VideoDisplay).stop();
      (child as VideoDisplay).close();
      (child as VideoDisplay).source = "";
   }
}
myContainer.removeAllChildren();

Granted, this code assumes you may have multiple movies in your container, although it can be combined with the previous solution to remove images and movies at the same time. Thanks to Ryan Phelan for their groundwork discovering this issue.

Adobe’s Broken Garbage Collector
For whatever reason, simply removing an image or video from the scene and setting references of it to be null is not enough for the garbage collector to recover the memory. If you have an application that cycles through two movies, for example, you may see the memory continue to grow drastically over time as all the previous copies of the video are kept in memory. Hopefully, Adobe will resolve this in future versions of the AIR runtime, but in the meantime developers must take extra steps to sure items have been unloaded and memory reclaimed.

The “Reinventing the Wheel” Anti-Pattern

Reinventing the Wheel As a moderator on the JavaRanch, I often come across posts asking how to reinvent features that are available in most application servers. In JDBC for example, I’ve had people ask how to implement their own database connection pooling and how to create their own JDBC driver. Often times the developer is trying to create something that already exists, but they are unsure how to use it. The general rule of thumb I tell programmers is, “If you feel like you are reinventing the wheel, you probably are”.

Review the API
If you ever get the feeling you are inventing the wheel, it’s a pretty good indication you are. In such situations, ask yourself “Is it likely a developer using the same component would need functionality X?”. If the answer is “yes”, then there’s a good chance there’s already such a feature in the API. Most often, reinventing the wheel comes from developers who are too lazy to review the API but not lazy enough not to rewrite the feature they think they are missing. Also, search the web. In some cases, you may need to download a new or updated library to get the feature you want, but this may give you access to even more features.

Your wheel isn’t better
Often called “Reinventing the square wheel”, it is likely the code you are recreating is worse, more buggy, and far less stable than the code you should be using. If you consider it for a moment, it makes sense a method built within the API should be better than a method built on top of the API. The API developer has access to private methods and objects that you do not have access to, and therefore your solution is limited by the public/external methods of the API. Furthermore, the fact the code is part of the API means scores of developers have hopefully reviewed the code for errors and performance enhancements.

That doesn’t necessarily mean the API implementation is better, but whenever I hear a developer say “I have a faster and cooler way of doing this than the way they do it in library” I cringe at the thought of what they may have written. If you do happen to create a better wheel, join the open source project and publish it for others to judge.

There’s always public humiliation
Many of the worst best articles that appear on the The Daily WTF come from programmers reimplementing the most basic functions of a language. One of the things that separates an experienced programmer from a beginner is the ability to recognize what tools in the API are needed for a task and how quickly they can be put together. And with that, I present a list of examples written by real developers and posted online for the world to see:

Any my personal favorite: I’ve heard from some good sources that the next version of SQL will use the word “GIMMIE” instead of “SELECT”

benefits of twitter lists

I really like twitter lists.  JobMob blogged about how to use them.  I agree with what they said, but have a different personal use for them.  Here’s my take on twitter lists.

I use twitter in several different ways.  Lists help me deal with those ways.

Current tweets

This is the traditional see things as it happens model that twitter was founded on.  I don’t read everything this way, but it is good for seeing a small number of the most recent tweets.

Before lists: I used TwitterFox now EchoFon to see tweets that come when I happen to be online.

After lists: Same.

Reading a lot of tweets

I get home after work and am curious what kinds of things have been tweeted that day.  This is where lists shine.  Even if you were reading the same number of tweets, it is faster to read them in logical groups rather than time.  And lists let you skip ones you don’t feel like reading.

Before lists: Follow less people so they wouldn’t clog up my tweet stream.  Use an RSS feed for some topics so they wouldn’t clog up my tweet stream but I could still read them.

After lists:

One time setup

  • Follow the people I was following by RSS so now I’m following everyone I want to
  • Add *all* my contacts to one list.  Some public lists and some private lists
  • Open all my lists in Firefox tabs and bookmark the set

To read

  • Open all tabs in Firefox.
  • Look at the ones I am interested in.  (for example, read jokes tab when I need a pick me up)

Reading tweets on a topic

Before lists: Scan tweet stream, search

After lists: Open the list pertaining to the topic.  Easy!

Public vs Private Lists

Public lists are good for things like

  • listing the JavaRanch moderators
  • jokes
  • topics of interest.

Private lists are good for things like:

  • hobbies you prefer to keep quiet
  • more sensitive topics (like the society of secret _____)
  • less than complementary lists (I have a “people-who-post-way-too-much” list for people who I am interested in periodically, but don’t want to read all their stuff)
  • “other” – a kitchen sink list until there are more people in that category – it doesn’t really make sense to others

Conclusion

Lists may not have been out long, but I rely on them already.  Combined with tab bookmarking, they are very powerful.  I imagine this twitter clients will catch up soon.

Follow me on twitter @jeanneboyarsky

http://twitterfox.net/