Rest

Yeah, so I’ve been working a lot and have been writing several devlogs but haven’t had a chance to post them until now. In short, I’ve been so busy working that I tend to use every last minute of the night performing "just one more test." I’m taking this short break to post these updates. I recommend starting with Tell Me Where It Hurts Part Part 1 and then moving on up. I hope this squelches any concerns that maybe I was slacking off this month. Time for a break.

Tell Me Where It Hurts Part 3: Security Checkpoints

This memory testing is quite the bug hunt. I’ve been testing between two computers and two browsers. I’ve been patting down every game object for illegal memory stashes. Offending code blocks are stripped and searched and sometimes even completely exterminated. Progress is being made little by little as I debug and optimize while innocent code is made to suffer inconvenient slow performing test operations.

It has been a tedious process but still productive. All this debugging has reacquainted me with some old code. Some of which I haven’t seen in months. It’s been nice getting back in touch. 😉

I still haven’t found that magic one-line-of-code that if fixed would solve all my problems…

1
2
3
4
5
6
7
8
////////////////////////////////////////////////////////
/////////////////////// PAIN IN BEHIND BEGIN ///////////
// set to false before testing
public static var GAME_BUGGED:Boolean = true;
// set to 0 before posting
public static var MEMORY_LEAK_RATE_KBS:int = 1024;
/////////////////////// PAIN IN BEHIND END /////////////
////////////////////////////////////////////////////////

9:45 PST – I finished coloring and formatting this series of devlog posts. That part about me "taking a break" mentioned above turned out to be an hour of devlog mayhem. The real break starts now.

9:46 PST – Okay, I’ll break for reals in a second but I think I just plugged another memory leak…

mem_test

I’ve been having trouble with the pikemen so I have them fight to the death for my amusement. Actually, I don’t even watch the battle. I just work on other stuff and wait for my computer to come to a screeching halt due to flash consuming all of my resources. At the end of this night I looked over and saw that they were still duking it out AND my ram was still not completely ravaged. As you can see, there has been 323 level changes (levels last just a few seconds) and still no problems! Yay. I’ve decided to tell you this because I want to completely jinx my code. Or do I? Take that Karma. Or don’t not take it not. See if I do not don’t care not so much so not… Everyone stay real quiet… … … okay I think the it’s safe now. I need food.

10:00 PST (-8 GMT) Posting…devlog

Tell Me Where It Hurts Part 2: Not (All) My Fault

So after doing some further tests I was able to pinpoint code that would result in memory leaks. The code itself looked harmless and functionally it worked.

I narrowed a leak to a “doSomething” function in my Util class. I knew it caused an error because when I turned the function into a no-op the leak went way. So I knew that something in that code was causing the leak. But just looking at it, it made no sense whatsoever why there was a leak.

Example original code:

public static function doSomething(clip:MovieClip):void
{
   var mc:MovieClip;         
   do some sort of gotoFrame logic on clip
   for all children in clip {
      if child is MovieClip {
         mc = MovieClip(child);
         doSomething(mc);
      }
   }
}

This code recursively does something on a movieclip and all of its children that are also movieclips.

public static function doSomething(clip:MovieClip):void
{
   do some sort of gotoFrame logic on clip
   for all children in clip {
      if child is MovieClip {
         doSomething(MovieClip(child)); // cast child and send
      }
   }
}

Notice that I removed the local variable “mc” and just passed a MovieClip casted version of child as the parameter. There was NO functional reason for this change. I really had doubts that this would have any affect. After all, “var mc:MovieClip” is a local variable and should be marked for garbage collection at the end of the recursive function call. The function does in fact end so don’t think it’s runaway recursion. We’re dealing with clips that are just 3 subclips deep at most and I use this function several times a second on many clips without any hanging.

When I tested the second version of the code there was no leak to be found. Undeniably the code change had some effect. Why?!? My theory was that since I was calling this static function from inside a non-static instance of an object that maybe Flash had some obscure rule about local variables inside static functions and it caused the program to hold on to all references to MovieClips thus preventing them from ever being garbage collected.

I don’t pretend to know everything there is about Flash or how it works. But something about this seemed real fishy. I often like to blame flash for its bugs but I do this mostly to complain about the IDE. I like to trust that the flash player is solid and without error… yeah, so naive. It’s not a good practice to blame the flash player because then you may write off real issues as “flash bugs” when in fact they are your fault. I try hard to give flash the benefit of the doubt. I’ve done so for this entire week. I’ve torn apart my code to pinpoint the causes for memory leaks. I’ve been rebooting my game practically one feature at a time just to find issues. This is how I found the issue mentioned above.

Even though I felt a little relieved that I’ve finally “fixed” one of the leaks, something didn’t feel right about that fix. I didn’t feel it was my fault. It felt like a hack solution and what bugged me the most was that I had no real understanding of the issue. There was no white-paper or release-notes that I was aware of that explained the issue I uncovered. I’m not sure I can even recreate the leak using anything but the complex environment of my game code. I’d love to make a lean code example of the issue without my entire game attached and submit it to Adobe and ask “why?”. I felt run down. A little defeated…

AND THEN… On a whim, I decided to test the code on a different machine. I should have done in the first place. It’s good practice to test the application in different environments with different browsers. I don’t know why I assumed my environment was error free. I was wrong.

I took the same exact game that had the leaky code and ran it in IE on a Windows XP 32 bit system. I was originally running on Windows 7 64bit using IE 32 bit. Using the same problematic version of my game but using the XP machine with latest flash installed the game had NO MEMORY LEAK. At that point I was mad. All this time I thought it was my fault. All this time I spent turning code on and off and locating obscure areas of code that my flash player decided it just didn’t like willy-nilly.

So now I go back and test variations of my game using past tests that failed before to see if they would pass this time on the different computer. Unluckily only some of the previous failed tests passed this time so I still had memory leaks that were my fault somewhere. OR the flash player on this other PC had a different kind of criteria for giving me faulty memory management. Either way I had to fix something because chances are I’m not the only one with the issue. However now I’m left second guessing whether or not the leaks are my fault or the player’s.

All I can do now is do further tests and isolate the areas of code that cause the game to break. Even if it’s a dumb flash bug and not my fault I still have to adapt since no amount of yelling at Adobe is going to fix this issue right this second.

The plus side to all of this testing is that it’s giving me a good understanding of how much memory certain features use. This will help me determine where I need to optimize the game to make it run smoother.

UPDATE: The saga continues… Read Part 3.

Tell Me Where It Hurts Part 1: For the Horde

I’m oh-so-close to posting a new update to Bowmaster Winter Storm (Alpha 0.0.1.9). I was so ready to start preparing the files for post and I blocked out an entire day to work on it. As I started working I discovered, much to my dismay, a memory leak! Dun dun dunnnnn! Well, I noticed that after performing some overnight tests using never ending battles that the game would use up all available memory and then crash the web browser… err…maybe I shouldn’t be telling you this.

To those of you who don’t know what a memory leak is it’s when a computer application starts using up memory but doesn’t free it up after it’s done using it. This is most often the developer’s fault due to a programming bug or just poor design. A simple flash example of how this might occur with poor design is that let’s say every time you killed a unit or closed a window that instead of removing it from memory the programmer coded it to just turn invisible by setting alpha = 0. Essentially this would cause the data to continue to exist in memory instead of being freed for use for new enemies and new windows. Unfortunately my memory leak was caused by something way more difficult to locate.

Anyway, it’s quite demoralizing when you set aside an entire day to work on play-testing and game balancing (the fun stuff) to then discover that you first need to fix a major issue instead. Not a great way to start out the day. Looking at the faded out crashed internet explorer window with a frozen image of bowmaster carnage in the background, I was not looking forward to hacking up my code to find the cause behind the memory leak. Image having an apartment that you just cleaned and organized and then getting a knock at the door – It’s the FBI and they have a warrant to search the place. Sure it has to be done but in so doing they’re likely going to trash the place. That’s what debugging memory leaks can be like. I just got done working on my unit-skinning system and re-integrating old units and adding new ones. Now I need to go into the code and start turning off stuff, add hard coded test functions to inspect output, and otherwise break the game in order to try to fix it.

Not knowing how long this was going to take or even where to start for sure, I did my best to divide and conquer. Unfortunately it’s not easy just turning off half the code without adding new bugs, but in theory if you could turn off areas of the program in half increments you can potentially narrow down the source of the problem fairly quickly. For example, if I suspected that some of the new unit skins may have been causing the problem, I could just not load those units and only load the ones that I know have worked in the past.

Not only is it difficult to find a memory leak, it may be difficult to replicate one in a short period of time because it may take a while before the impacts are noticeable. I needed a way to accelerate the process of replicating the issue. I hacked my game to load tons of units in random areas of the map so they would instantly engage in battle. With more data being loaded and unloaded more frequently I could now inspect the memory usage using the Windows system processes inspector to see the memory increase quicker. I was also able to get the web browser to crash in a matter of minutes instead of hours. Yay!

It may sound odd to be happy to cause the game to crash, but when debugging it’s essential to be able to recreate the issue. With this step complete I was ready to start turning off sections of my code to see if doing so would remove the issue. The usual suspects for potential memory leakage were the new units, the elaborate special death animations (slice in two, electrocute etc.), and certain custom units like pikemen and dragons that have special ways in which they attack.

Technically speaking, there are few known best-practices that will prevent memory leaks from occurring. If you’re not a programmer or you do not care about these tips then feel free to skip down to where I talk about how dumb I am.

Tips:

1. Use weak references when adding event listeners.
addEventListener(“eventString”, listenerFunc); // wrong way
addEventListener(“eventString”, listenerFunc, false, 0, true); // correct way. The last three parameters are optional but the default useWeakReference parameter is set to false so you need to set it to true.

2. Even if you use weak references, call removeEventListener to explicitly remove event listeners when you know they aren’t being used.

3. Adding code to clips embedded in a timeline may cause memory issues. For example if you add a listener to a clip on the timeline and then that clip is replaced by a blank keyframe you may have memory problems. Another example is if you give a clip on the timeline an instance name and then move that clip to a different layer with the same instance name you may have memory problems.

4. Remove or nullify references to unused objects. An object will continue to stay in memory if there are references to it. In Bowmaster for example, I keep a singleton reference to the LevelManager class instance for easy global access in other classes. However, this instance is only relevant when the player is in-game and is not relevant when viewing the main menu screen. Therefore I need to make sure to set the global static singleton variable to null when the game window is closed otherwise all objects still referenced by the LevelManager will not be freed.

 

How dumb I am…

So despite how smart I may sound listing all those tips above, I felt like a total flash noob spending the entire day trying to locate the problem. I kept turning on and off code and checking the results but every time I wasn’t able to specifically pinpoint the issue. I thrashed for hours, 12 full hours, trying different things and documenting the results. At some point you just need to call it a day, and I probably wasn’t very productive or efficient for those last four hours I worked, but it’s hard to stop when you think to yourself, maybe if I try just one more thing…

The next couple of days I was forced to only work in short increments, but I was making progress. I eventually turned off all the units except the grunt and started testing one skin at a time. I discovered that just one of the five unique grunt skin sets was causing a memory leak. Guess which one… It was the orc. Yep, I created a new grunt unit that used the same basic animation as the skeleton foot soldiers but changed the graphics to look like an orc. And then for some reason, in an act of defiance, the orc decided to crash my game. I give him life and this is how he repays me? By hording all the memory and never giving it back? Bad orc! Bad! (::scrohboo::) So it wasn’t just the fact that he looked like an orc — that would just be silly. Specifically I narrowed it down to some embedded code that I used to animate the shine on the orc’s sword. What was unsettling was that I used this embedded code approach before in other animations. I’m thinking that the new skin redesign may have made this code incompatible, or maybe it was always broken and I just never noticed the memory leak until now.

Luckly, after some tweaking I was able to get the shine animation to work AND not crash the web browser (i.e. no memory leak), but I’ll need to inspect other areas of the game that use similar embedded code and fix those as well.

It was one of those traumatic software development experiences where there’s no hope and you wonder if you’re going to have to redesign the entire application… Yeah, maybe I blamed flash a little too. I was quite vexed about this issue. I did not want to crash people’s web browsers. I care about the user. Yeah, maybe the issue will only affect those that play for hours straight without refreshing the browser, but I’m not going to deny them that opportunity just because I didn’t want to fix a bug.

On one hand it looks as if it took several hours just to find and fix one bug. On the other hand, I just spent several hours towards the goal of ensuring that the user has an error free experience. And in the process of doing so I’ve implemented several useful debugging systems that will allow me to test the game much easier in the future.

Yeah, so maybe it’s not so easy to skin an orc. But in the end it will be worth it. Stay tuned. You’ll see.

UPDATE: Not so fast jase… don’t think this is over. Read Part 2.