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: , , ,

  1. #1 written by Benj July 22nd, 2010 at 09:30

    Call me paranoid, but I never trust that Timers and ENTER_FRAME events will play nice with each other, at least not when it comes to critical timing issues.

  2. #2 written by senthil kumaran chinnthambi August 24th, 2010 at 00:45

    —————————————-

    I love your banner …. Is it done by using box2D? and flames by tracking the velocity?

    —————————————-
    http://www.thirstyneurons.com
    —————————————-

  3. #3 written by The Horseman August 27th, 2010 at 12:05

    @ senthil kumaran chinnthambi
    Hi Senthil,

    I am using Box2D for the physics, as I wrote a few entries ago. The flames are a “secret sauce” of mine that involves bitmaps and filter effects. 🙂 And yes indeed, the velocity of the physics bodies is used to determine whether something is currently burning.

  4. #4 written by nicemandan October 29th, 2010 at 13:28

    Ran into this issue today. Interestingly the timers went all screwy my game had the sound off. When I switched the sound on, the timers worked!

    The sound on/off toggle in my game checks a flag before calling play on the sound.

    As the deadline was today (!) I simply made the “sound off” functionality turn the volume down to zero. This kept the mp3 playing and my game alive. A terrible solution, but it worked in the short space of time I had.

  5. #5 written by The Horseman November 4th, 2010 at 06:24

    That’s an intereting scenario nicemandan. What about the timers was screwy? Was there something listening for Event.SOUND_COMPLETE somewhere that touched the timers as a result of the event handler?

  6. #6 written by JCG May 22nd, 2011 at 21:04

    Old comment thread, but for anyone else looking, nicemandan’s “success” is due to this, also mentioned by Kaourantin:

    “For backwards compatibility reasons we override the 2 frames/sec frame rate to 8 frames/sec when audio is playing.”

  7. #7 written by M.A.D. January 12th, 2012 at 03:11

    Hello,
    I have a problem with my animations – they slow down to 2fps when inactive. Now I know what’s causing it, but I want to know how to ‘fix’ it. How can I make sure they run at their set fps even in inactive browser tab? I’m not a flash newbie, but not a flash expert either. It seems all animations but mine work even in inactive browser tabs. What am I missing here? It’s been long since FP10.1, so there must be a solution to that now.