Archive for the ‘Flash Pitfalls’ Category

Flashing your C String

On a project I worked on a few months ago, I was tasked with taking data from a binary source file, reading it into Flash as UTF Bytes (eg: a ByteArray) and parsing the resulting ByteArray as a String. Straightforward enough, right?

What I know of the file to parse is that it is a very long list of words compressed and encoded, and that it needs to be decoded at runtime inside the swf. Fortunately, I have the algorithm for decoding the string on-hand, so I know I can implement this with relative ease. All I have to do is load the .dat file containing the list and then run the resulting byte array through the parser and get my list of words.

var ba:ByteArray = myImportedByteArray;
ba.position = 0;
var encodedString:String = ba.readUTFBytes(ba.length);
trace(encodedString);
/* My expected result was something akin to:
"Header Metadata - (Jibberish representing encoded list goes here)"
*/

So funny enough, when I do that what do I get instead?

"Header Metadata"

Huh.

I spent a good long time puzzling over where the encoded word list was in all of this. I could open the .dat file in Eclipse, and plainly see the list right there. I wondered if perhaps there were some sort of problem reading the data. Maybe the ByteArray was incomplete? No, because when I traced ba.length it indicated that the array was well over 90,000 bytes in size. Definitely too many to simply be “Header Metadata”. Next, I did this:

// 200 chosen simply for the sake of an easier to read log...
ba.position = 0;
var byte:Number;
while(ba.position < 200){
	byte = ba.readByte();
	trace(byte, String.fromCharCode(byte));	
}

What I recieved in the output window was in fact the first 200 characters of the file just as I’d expected them to be!

72 H
101 e
97 a
100 d
101 e
114 r
32  
77 M
101 e
116 t
97 a
100 d
97 a
116 t
97 a
0
32  
63 ?
32  
0
102 f
111 o
111 o
98 b
97 a
46 .
46 .
46 .

This gets more and more curious by the moment. At some point though, the lightbulb goes on. Look at this right here….

100 d
97 a
116 t
97 a
0        // < -- see that 0?  
32  
63 ?
32  
0        // < -- and that 0?

Anatomy of a String

So, in Flash-land we very seldom have to know about what might be going on under the hood of the String class. I mean, we just declare Strings, read them, print them, concatenate them, and in general just don’t really care much about how they work. It is not like this in all languages, however. Hop aboard the black stallion, for the Horseman is about to take you to a magical world known as “C Strings.”

The C language generally operates “Close to the metal” of a machine. You can think of it as an abstraction that allows you to write code that is then directly translated into Assembly-level instructions, that are then executed by the machine’s processor. In that sense it is a “High level” language (at least in comparison to writing Assembly by hand) but it is lower level than what an ActionScript or Java programmer would have to deal with as our respective Virtual Machines abstract over the nitty-gritty of memory allocation and deallocation, and direct pointer manipulation inherent in C. So what does a String look like in this lower level world? It is ultimately nothing more than an Array of char values.

char someString[10]; // an array of char values with a length of 10

It needs to be pointed out that there is a very important distinction between C Arrays and ActionScript Arrays. C Arrays are fixed-length. If you declare an Array to have a length of 10, then a contiguous set of memory addresses, of a size capable of storing 10 units of the data (in this case, char values) is allocated for that Array. That’s all. Nothing else happens. An Array in C is not an Object, so it doesn’t have a notion of a “length” property, nor does it have .push() or .pop() functions. Unless you know the length already, you can iterate your way past the end of the Array and keep on going into some other variable’s data… possibly even into undefined space.

This is considered “a very bad thing to do”. (As an existential aside about walking off the end of an array, please read this blog post by Steve Yegge)

But wait, if you can’t know the length of an Array in C then how can you possibly know when you’ve reached the “end” of a string?

Good question! Here’s what the string “Hello World!” looks like in C:

char *foo = "Hello World!";
// looks to the machine like this in ASCII....
// {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 0}

Each of those numbers maps to a Unicode representation of a letter, so for example 72 maps to “H” while 33 maps to “!”. If you want, to see this in the Flash context you can set up a KeyboardEvent listener and trace the event. You’ll find the keyboardEvent.charCode property will match the above.

But do you notice anything funny here? “Hello World!” has 12 chars, but that array above has 13 entries! The very last one of course being 0. Now why is that?

In C, when you want to know if you’ve reached the end of a string, you’ll look for what is called a null terminator. In C, 0 can be considered a null value and so when a string is declared it has a length equal to the length of the characters entered into it plus one for the terminating 0. Any code that wants to parse the string can know that it should stop when it hits a 0 because to keep going after that could lead anywhere! And we certainly wouldn’t want to add some instruction set for connecting to the printer to your string… or worse, overwrite it with some random garbage!

And so this brings us back to our little ByteArray in Flash and the encoded word list. As you can see, the header metadata is immediately followed by a 0. In C terms, this file is in fact 3 strings instead of 1. Knowing this, and observing the fact that Flash’s String object seems to believe that this 90,000+ length ByteArray is in fact a string of a mere 15 or so characters, we can deduce that under the hood Flash’s String is C’s string.

My algorithm then, had to account for this fact and once I knew that Flash would treat a 0 byte as a null terminator when calling readUTFBytes, was able to successfully reach the word list.

Tags: , , , , , ,

4 Comments


How Flash Player 10.1 “broke” my banner (and how I fixed it)

Maybe you’re one of the people who upgraded recently to Flash Player 10.1. If so, you probably managed to see my banner doing things that I didn’t intend it to when I created it for Flash Players 9 – 10.0. The flaw was subtle, and one that you wouldn’t ever find simply by watching the animation. So how did I find it?

Let’s go back in time a few months, back when Adobe was still bursting with enthusiasm over the prospect of having Flash Player on Apple’s mobile devices. They worked feverishly to implement many changes to the way the Flash Player behaves to minimize its CPU consumption, and as well to reduce potential strain on the batteries of the new breed of mobile devices. One of these changes was to dynamically change the rate at which code executes when the player is not “in focus” (eg: you have a browser with three tabs open, and the Flash Player is open on one of the non-active tabs).

Here’s Tinic Uro’s blog entry in which he gives a very detailed accounting of the changes. For those who don’t wish to read it all, here’s the section that broke my banner:

Implications for user experience

In Flash Player 10.1 SWFs on hidden tabs are limited resource wise. Whereas they would run at full speed in Flash Player 10.0 and before (note though that we NEVER rendered, we only continued to run ActionScript, audio decoding and video decoding), we now throttle the Flash Player when a SWF instance is not visible. Doing this change was not easy as I had to add many exceptions to avoid breaking old content. Here is a list of some of the new rules:

Visible:

* SWF frame rates are limited and aligned to jiffies, i.e. 60 frames a second. (Note that Flash Playe 10.1 Beta 3 still has an upper limit of 120 which will be changed before the final release)
* timers (AS2 Interval and AS3 Timers) are limited and aligned to jiffies.
* local connections are limited and aligned to jiffies. That means a full round trip from one SWF to another will take at least 33 milliseconds. Some reports we get say it can be up to 40ms.
* video is NOT aligned to jiffies and can play at any frame rate. This increases video playback fidelity.

Invisible:

* SWF frame rate is clocked down to 2 frames/sec. No rendering occurs unless the SWF becomes visible again.
* timers (AS2 Interval and AS3 Timers) are clocked down to 2 a second.
* local connections are clocked down to 2 a second.
* video is decoded (not rendered or displayed) using idle CPU time only.
* For backwards compatibility reasons we override the 2 frames/sec frame rate to 8 frames/sec when audio is playing.

kaourantin.net – ‘Timing it right’

Yes, code execution and frame redraws are now limited to 2FPS when the swf is not in the active window. How did that break anything, you might wonder? The danger lies in the new interplay between the ENTER_FRAME event and the Timer object. Judging by the information above, you’d think that there would be no conflict, as Timers and ENTER_FRAME events both dial down to 2FPS, but that doesn’t seem to be the case.

When I created the banner, I used the following structures to control the various events you see:

  • An ENTER_FRAME listener, on which I update the physics simulation and the flame effects.
  • A Timer that spawns a new statement every 5 seconds, to send it crashing to the ground.

The issue here is that, in spite of what is written in kaourantin.net, what actually happens is that while the ENTER_FRAME events do in fact get ratcheted down to 2FPS, the Timer on the other hand still executes every 5 seconds! This means that if you tab away from the banner for a few minutes and then come back a giant rain of broken letters all fall from the sky at once. Well, that’s not so bad right? Isn’t that just a different kind of apocalypse, after all? It would be, if it weren’t for the other side effects…

  1. Once enough words spawn, the mess at the bottom auto-cleans itself, so returning to the page left an odd jumble of letters floating inexplicably
  2. Leaving it in the background long enough seemed to cause a memory backup in Box2D, such that words eventually simply failed to materialize, throwing errors.
  3. Clicking the “Dismiss All” button to silence all the errors and leaving the banner to run overnight caused a memory leak in Firefox that froze the browser.

What was I to do? Well, the only thing I reasonably could do at that point was to change the banner such that the spawn timer was no longer a literal Timer object, but instead was a fake “timer” that counted up by 33 “fake” milliseconds on every ENTER_FRAME event, so that I could get the same desired effect of a new word being spawned every 5 seconds as I had previously. Why use “fake” milliseconds instead of real ones? Because real milliseconds would put me right back in the situation of spawning a new word every 5 seconds while the simulation runs at 2FPS. So, since this blog is all about ActionScript pitfalls and how to avoid them, here’s the latest one learned from hard experience:

Do not mix two different methods of timekeeping in the same application. Either rely on ENTER_FRAME, or Timer exculsively for all things. Not both.

Maybe I’m the fool for trying to mix different methods of keeping time? Somehow I don’t think so. This definitely seems like one of those instances where perfectly valid and accepted practices of the past have been changed dramatically, potentially stranding people who were simply following accepted practice. Not a first for Adobe.

Has anyone else run into weird backwards-breaking issues regarding Timers, ENTER_FRAME, and other custom time-keeping methods such as the use of getTimer() now that Flash Player 10.1 has changed so drastically?

Tags: , , ,

7 Comments


“I put a function in your function, so you can process while you process!”

Maybe you’ve seen this before:

public function foo():void{
    // a function in a function?
    var onLoad:Function = function(e:Event):void{
        addChild(loader);
    }
    var loader:Loader = new Loader();
    loader.addEventListener(Event.COMPLETE, onLoad);
    loader.load(new URLRequest("someSwf.swf"));
}

It appears that the developer in question has written a function inside of a function. They were at least kind enough to assign it to a variable. They could have created one that is completely anonymous.

So, is there something wrong with this? In ActionScript 3 the answer is it kind of depends.

There are legitimate reasons why a developer might wish to do this, and they involve coding around a weakness in the Event model. The most interesting of these reasons is that this style represents the only way you can get away with early binding of variables. In doing so however, it’s easy to create objects that can never be eligible for garbage collection. Notice in the above example that the developer never removed the listener! In the examples to follow, I will exercise due diligence and remove them explicitly.

As an example, I’ve seen developers write code like this, thinking that the value of count will be “fixed” in the event handler to what it was when the handler was assigned:

private var count:int = 0;
private const MAX_COUNT:int = 10;
 
public function foo():void{
    while(count < MAX_COUNT){
 
        var onLoad:Function = function(e:Event):void{
            // offset the loader's x value by width * the number of images loaded.
            loader.x = loader.width * count;
            addChild(loader);
            e.currentTarget.removeEventListener(Event.COMPLETE, onLoad);
        }
        var loader:Loader = new Loader();
        loader.addEventListener(Event.COMPLETE, onLoad);
        loader.load(new URLRequest("someSwf.swf"));
    }
}

Only to discover that the value contained in count is not at all bound at the time the listener is added. They find that *all* their images end up at content.width * 10. Their next impulse is to “find a way to pass the current count to the event handler”, but you cannot do that. This:

// trying in vain to pass 'count' to the listener...
 loader.addEventListener(Event.COMPLETE, onLoad, count);

Is simply not valid AS3 code. There are two ways around this. My preferred method is to keep your real count at the class level, and to increment it in onLoad rather than to rely on the foo() function, and to never use a nested inner function. This gives the class a very plain set of signatures that can be read and interpreted in a list, and whose namespaces can be changed as needed to allow or deny access from both the outside and the inside. I find it worth the extra few lines of code and scrolling in the short term to have something easier to read in the long term.

 
private var count:int = 0;
private const MAX_COUNT:int = 10;
 
public function foo():void{
    // remove the count from foo, and use a local variable.
    var i:int = 0;
    while(i < MAX_COUNT){
        var loader:Loader = new Loader();
        loader.addEventListener(Event.COMPLETE, onLoad);
        loader.load(new URLRequest("someSwf.swf"));
        i++;
    }
}
private function onLoad(e:Event):void{
    var content:DisplayObject = e.currentTarget.content as DisplayObject;    
    content.x = content.width * count;
    this.addChild(content);    
    // increment the count here.
    count++;
    e.currentTarget.removeEventListener(Event.COMPLETE, onLoad);
}

So as you can see, there’s no need to use the listener-within-a-function. Why then, does it remain tempting for people? Aside from the fact that it requires less scrolling around the page and you can just write out the function in a place where you can see everything you’re thinking about, there is a special way to do this that allows you to use early binding. Get ready, because we’re about to take it another level down the rabbit hole.

public function foo():void{
    // a function in a function?
   for(count ; count < 10 ; count++){
        var onLoadHandler:Function = function():Function{
            var c:int = count;
            // with another function in a function inside of it???
            var handler:Function = function(e:Event):void{
                var count:int = c;
                var displayObject:DisplayObject = e.currentTarget.content as DisplayObject;
                displayObject.x = displayObject.width * count;
                addChild(loader);
 
                // IMPORTANT: Remember to remove your listener!
                e.currentTarget.removeEventListener(Event.COMPLETE, handler);
            }        
            return handler;
        }
        var loader:Loader = new Loader();
        // Call the function onLoadHandler to get the *real* function that is used as the listener as a return value
        loader.addEventListener(Event.COMPLETE, onLoadHandler());
        loader.load(new URLRequest("someSwf.swf"));
    }
 
}

Once you start nesting functions this deeply and returning the inner functions as values to be used, you’re stepping across the line of Object Oriented Programming into Functional Programming, though it’s a half-baby-step in this case. You’ll notice in this instance that the value of “count” in the innermost function is bound to the value of “count” at the class level as it existed when the originating function was declared in the for loop because of the intermediary “c” variable. This works because of the acrobatics involved in working across so many scopes in a single function call. I’ll come out and admit that while it can be initially confusing to see so many functions nested, it *is* convenient not to have to declare extra class level variables or scroll around looking for other functions in the code. You may wonder then why I prefer not to use them.

  • Function calls are processor intensive. Inside a long loop, calling so many functions adds considerable overhead.
  • It obscures your API. These inner-functions and variables never appear on a class diagram.
  • You can not directly touch these functions from anywhere except the scope in which you create them.

1. In my post about Array Optimization you’ll note that there’s nothing particularly intensive happening in those loops. Imagine however, that there *is* something to do in all those locations. There are no empty array locations, and for each item in the array there is a function call. Now imagine that there are two or three function calls. In fact don’t just imagine it, benchmark it yourself. You’ll find that function calls simply consume a great deal more resources than code written inline.

2. It’s one thing to write OOP code with intentional encapsulation such that objects don’t know much about each other. It’s another thing to write it such that the objects don’t know much about themselves. That’s essentially what’s happening when you rely on multiply nested function-scoped functions. It makes the code harder to understand at a glance from a high level. “I know that there’s a function that says to load images, but I don’t see where that’s being handled and I cannot override it in a subclass without overriding the loading function too.

3. This is the really big one, and the one that has the most room to trip you up in weird ways (hence the “pitfall” categorization of this entry). While Flash does offer you the option to add an event listener as a “weak reference” for aid in garbage collection, that doesn’t mean that once the object is eligible for gc that the object has ceased to exist, or that it will stop dispatching events. Far from it! With asynchronous events such as Event.COMPLETE (in the context of loading external content), TimerEvent (all of them), and even the synchronous Event.ENTER_FRAME, you’ll find that these events still dispatch, even if the references are weak, and even if the dispatching object is eligible for garbage collection. How do you remove an event listener that you don’t have any access to outside the scope in which it’s added? The only answer is “you have to do it inside the handler itself” which may not be practical or even possible under many circumstances. It is possible in the context of the Loader class (as demonstrated above) but the waters become murkier with ENTER_FRAME or TimerEvent(s), as the function now needs to undertake the responsibility of checking whether it should somehow remove itself from its dispatcher every time it executes, and possibly aborting execution if it should be removed.. This of course adds CPU overhead to the code, and if the event is dispatched frequently represents a large amount of needless processing.

You’re probably wondering why The Horseman would even tell people that this is possible if he’s so reluctant to use these nested functions himself. The simple answer is that people are going to do this anyway. No matter my own personal preference, there will always be coders whose first inclination is to use functions inside functions, and that’s fine. There’s a whole paradigm based around passing functions and relying ONLY on function scope, in fact! The problem comes when people who don’t know the risks and the trade-offs are careless about using them, particularly in an otherwise Object Oriented environment. Consider this to be a primer on those risks and the trade-offs, at least in the context of ActionScript 3. There are more to consider, but that’s for another time.

Tags: , , , ,

No Comments