{"id":383,"date":"2010-04-06T11:29:35","date_gmt":"2010-04-06T19:29:35","guid":{"rendered":"http:\/\/www.lostvectors.com\/blog\/?p=383"},"modified":"2010-10-11T11:57:50","modified_gmt":"2010-10-11T19:57:50","slug":"tell-me-where-it-hurts-part-1-for-the-horde","status":"publish","type":"post","link":"https:\/\/www.lostvectors.com\/blog\/2010\/04\/06\/tell-me-where-it-hurts-part-1-for-the-horde\/","title":{"rendered":"Tell Me Where It Hurts Part 1: For the Horde"},"content":{"rendered":"<p>I&rsquo;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&#8230; err&#8230;maybe I  shouldn&rsquo;t be telling you this.<\/p>\n<p>To those of you who don&rsquo;t know what a memory leak is it&rsquo;s  when a computer application starts using up memory but doesn&rsquo;t free it up after  it&rsquo;s done using it. This is most often the developer&rsquo;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&rsquo;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.<\/p>\n<p>Anyway, it&rsquo;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 &ndash; It&rsquo;s the FBI and they have a warrant to search the place. Sure it has to  be done but in so doing they&rsquo;re likely going to trash the place. That&rsquo;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.<\/p>\n<p>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&rsquo;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. <\/p>\n<p>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!<\/p>\n<p>It may sound odd to be happy to cause the game to crash, but  when debugging it&rsquo;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.<\/p>\n<p>Technically speaking, there are few known best-practices  that will prevent memory leaks from occurring. If you&rsquo;re not a programmer or you  do not care about these tips then feel free to skip down to where I talk about  <a href=\"#2010_04_06_how_dumb\">how dumb I am<\/a>.<\/p>\n<p>Tips:<\/p>\n<p>1. Use weak references when adding event listeners.<br \/>\naddEventListener(&ldquo;eventString&rdquo;, listenerFunc); \/\/ wrong way<br \/>\naddEventListener(&ldquo;eventString&rdquo;, 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.<\/p>\n<p>2. Even if you use weak references, call removeEventListener  to explicitly remove event listeners when you know they aren&rsquo;t being used.<\/p>\n<p>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.<\/p>\n<p>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.<\/p>\n<p>&nbsp;<\/p>\n<p><a name=\"2010_04_06_how_dumb\"><\/a>How dumb I am&#8230;<\/p>\n<p>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&rsquo;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&rsquo;t very productive or  efficient for those last four hours I worked, but it&rsquo;s hard to stop when you  think to yourself, maybe if I try just one more thing&#8230;<\/p>\n<p>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&#8230; 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&rsquo;t just the fact that  he looked like an orc &#8212; that would just be silly. Specifically I narrowed it  down to some embedded code that I used to animate the shine on the orc&rsquo;s sword.  What was unsettling was that I used this embedded code approach before in other  animations. I&rsquo;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.<\/p>\n<p>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&rsquo;ll  need to inspect other areas of the game that use similar embedded code and fix  those as well.<\/p>\n<p>It was one of those traumatic software development experiences  where there&rsquo;s no hope and you wonder if you&rsquo;re going to have to redesign the  entire application&#8230; Yeah, maybe I blamed flash a little too. I was quite  vexed about this issue. I did not want to crash people&rsquo;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&rsquo;m not going to deny them  that opportunity just because I didn&rsquo;t want to fix a bug.<\/p>\n<p>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&rsquo;ve implemented several useful debugging systems that will allow  me to test the game much easier in the future.<\/p>\n<p>Yeah, so maybe it&rsquo;s not so easy to skin an orc. But in the  end it will be worth it. Stay tuned. You&rsquo;ll see.<\/p>\n<p>UPDATE: Not so fast jase&#8230; don&#8217;t think this is over. Read <a href=\"http:\/\/www.lostvectors.com\/blog\/2010\/04\/08\/tell-me-where-it-hurts-part-2-not-all-my-fault\">Part 2<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&rsquo;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!<\/p>\n<p> <a class=\"continue-reading-link\" href=\"https:\/\/www.lostvectors.com\/blog\/2010\/04\/06\/tell-me-where-it-hurts-part-1-for-the-horde\/\"> Continue reading <span class=\"meta-nav\">&rarr; <\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-383","post","type-post","status-publish","format-standard","hentry","category-devlog"],"_links":{"self":[{"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/posts\/383","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/comments?post=383"}],"version-history":[{"count":5,"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/posts\/383\/revisions"}],"predecessor-version":[{"id":393,"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/posts\/383\/revisions\/393"}],"wp:attachment":[{"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/media?parent=383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/categories?post=383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lostvectors.com\/blog\/wp-json\/wp\/v2\/tags?post=383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}