views:

541

answers:

7

I'm currently working on a very large Flash platformer game (hundreds of classes) and dealing with an issue where the game slowly grinds to a halt if you leave it on for long enough. I didn't write the game and so I'm only vaguely familiar with its internals. Some of the mysterious symptoms include,

  • The game will run fine for a determinate amount of time (on a given level) when all of a sudden it will exponentially start leaking memory.
  • The time it takes for the game to hit the point where it leaks exponentially is shorter when there's more sprites on the screen.
  • Even when nothing is being visibly rendered to the screen, the game slows down.
  • The game slows down faster with more frequent sprite collisions.
  • Completely disabling the collision code does slow down the degradation but doesn't prevent the game from eventually dropping frames.

Looking at the source and using Flex profiler, my prime suspects are,

  • There are many loitering objects, especially WeakMethodClosure, taking up large amounts of memory.
  • The program makes extremely extensive use of weak event listeners (dozens dispatched per frame).
  • BitmapData is being copied every time a new sprite is created. These are 50x50 pixel sprites that spawn at about 8 sprites per second.

I know it's next to impossible to tell me the problem without seeing the source, so I'm just looking for tidbits that might help me narrow this down. Has anybody experienced this evasive performance degradation in their own projects? What was the cause in your case?

A: 

Sounds like you need to profile your application to see what is happening.

This thread had a couple of suggestions, but, ultimately, you will need to just put in code to help determine what is going on.

http://stackoverflow.com/questions/1255132/profiling-actionscript-3-code

You may want to see if you can just run some smaller parts over a period of time and see if you see a slowdown.

You may want to unit test your application, so you can run various parts rapidly, looking for memory leaks. One framework is: http://asunit.org/, and another is: http://opensource.adobe.com/wiki/display/flexunit/

Unit testing is something I use a great deal for profiling, so you can test at the top level of your game, run it thousands of times, looking for problems, then run each part and see which has problems, and just work your way down. This is a manual process, but if the two ideas in the SO thread listed in the beginning don't help, this may be your best approach.

Are you using too much memory? Or is your cpu usage too high?

James Black
The question mentions memory leaks, so I'm guessing that cpu usage isn't the problem.
David Locke
I am trying to see if there are other problems besides what he is guessing. Unfortunately, when I have guessed where my programs have problems, I tend to be wrong, which is why I depend on profiling so much.
James Black
I am wondering if excessive garbage collection leads to a degradation of the program, due to having too many objects being generated too fast.
James Black
A: 

First determine if its a memory or processor limit you are hitting. It sounds like the later, seems like there are many objects doing stuff around ... likely those extra sprites aren't being freed well. Look for dependencies among objects / variables / anything in those events, make sure the sprites are removed, pay attention to any handlers of EnterFrame or recurring events.

eglasius
+1  A: 
  • Avoid anonymous methods - change them into class level methods.
  • Use weak reference in addEventListener and/or make sure you remove all the listeners of an object before removing it with removeChild
  • Make sure you removeChild all the sprites instead of just letting them fly off the screen. Also, if possible, reuse the sprites instead of creating new ones.
Amarghosh
A: 

You should consider object pooling if you have a lot of creation/destruction going on, especially with heavy objects like bitmapdata.

see Object Pool class

sharvey
This is a great idea once I identify which resources are causing the bottleneck.
Kai
A: 

It sounds far more likely that you are capping out on processor speed than memory. You have to try extra hard to memory cap a Flash application.

Fortunately there are a lot of easy things you can do to keep CPU down...

1) Stringently manage event listeners for everything, especially mouse listeners. Do you have $texas event listeners on all your sprite objects? That could be a problem.

2) Access arrays using int or uint instead of Number. This is huge, and this is one of those backwater Adobe tricks. Accessing array object with int and uint is way faster than Number and if you do a lot of iteration (and it sounds like you do) this could shave precious milliseconds off your frame execution.

3) In the same vein as #2, monitor your math operations and what types you are using for certain operations. The slowest thing you can do in math operations for AS3 is repetitive casting (feeding ints to a function that returns a Number), or performing basic operations like add and subtract on Number instead of int.

The great thing about having a wtfhuge program like this in Flash is that even a minor optimization change could have a major impact on performance. I once toyed with a raytrace engine in AS3 where I declared one extra variable and it killed my FPS from 30 to 23.

Jasconius
I'm sure that my game is breaking these rules in at least a few places. I hope it's as easy as that!
Kai
+3  A: 

I recently completed a optimization of an large project. And I can give you some architectural advices:

  1. Main principle – try do as little as possible function / events calls
  2. Get rid off all but one onEnterFrame / onInterval / onTimer cycles. Do everything you need in one general event call. You probably will need a lot of static arrays for storing processed object references.
  3. Do your graphics / render stuff also in one main loop
  4. Try use big (probably prerendered) canvases instead of small sprites / bitmaps. Usually it usable for backgrounds. But also working good for a smaller objects (like trees, platforms, etc)
  5. Rid off small bitmap resources, assemble it to one tile-sheet and draw your stuff directly from it, through source–rect property

I hope its helps you! Memory leaks – such headash.

P.S. Test your game in different browsers, IE – most leaking of all, sometimes it don`t clear memory every after refresh.

peko
I think this is great advice for somebody just starting a large gaming project and wondering how to best structure it.
Kai
A: 
Flash has a rather infamous issue (many consider it a bug) that causes event listeners for timers and the ENTER_FRAME event to not get garbage collected, even if they were weakly referenced. So, even though it's good practice to use weakly referenced events, you should still remove all your event listeners when they are no longer needed.
BernzSed
After a quick search for Event.ENTER_FRAME I've come up with 18 matches, so it's safe to say that the issue could be here as well.
Kai