Posts Tagged ‘ENTER_FRAME’

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