Nov
11

“Multi-threading” in Flash Mike Baker

Actionscript, Flash

More often than not, in Flash and ActionScript, user experience is everything and part of that experience includes a fluid/responsive UI. In some cases large amounts of data need to be processed as well, whether it be plotting 1000’s of points on a graph or parsing the configuration data of your sprawling <insert generic Facebook game> plot of land.  In the worst of cases even the most optimized logic will take time  eventually breaking past Flash’s default timeout of 15 seconds.

Error: Error #1502: A script has executed for longer than the default timeout period of 15 seconds. 
at Untitled_fla::MainTimeline/frame1()

The simple solution to this problem is to go into your publish settings and increase the script timeout limit:

File -> Publish Settings... -> Flash : Script time limit:  seconds

But this really doesn’t solve the real problem at hand. Yes, the error is no longer thrown but the UI will still remain completely unresponsive during the time the script is processed and there is no way to know for sure that your grandmother wont  hit the newly set limit on her old old machine (complete with turbo button).

It’s well known that the Flash runtime doesn’t support multi-threading, at least not in the conventional sense. The only separate thread you can do work on in Flash is through PixelBender which, can be useful but is really only limited to number crunching.

In 2002, Mario Klingemann suggested that separate Flash applications on a page would run on separate threads http://www.quasimondo.com/archives/000071.php. I haven’t tested this myself yet but I get the same execution time running his test app in ‘single’ and ‘multi’ thread mode leading me to believe it doesn’t work. Regardless having two flash apps on one page, communicating through local connection, isn’t exactly conventient, particularly for local testing!

A little more recently, Senocular wrote a great post on Asynchronous ActionScript Execution but I wanted a class to help with the readability/execution of asynchronous execution. I wanted something more like the BackgroundWorker Class found in Silverlight for simplicity.

Using the information from Senocular’s post the framerate of a SWF can be maintained by limiting the amount of processing done on a single frame. So we should be able to write a class that takes in a function and calls it as many times as possible within the limits of a single frame and dispatching a progress event. It should also have a great catchy name like… oh I don’t know, AsyncHelper. I wrote a test application to make use of the AsyncHelper below:

As you can see the spinning square locks up completely when processed without being spread over many frames. While it remains fluid when the processing is spread out over a number of frames, but its not all roses and candy. In my tests and as you can likely see, the processing done with the aid of AsyncHelper takes about 15%-30% longer than the same processing done in one frame.

I admit the 15%-30% was recorded on a limited set of machines so I’d love to see some of the numbers readers achieve. Leave your specs (processor, flash version, etc) in the comments and let me know what the difference between asynchronous and synchronous operations was. Over the coming months I’ll be looking to improve the AsyncHelper to try and widdle down that 30% loss in performance.

Much of the slow down can be attributed to the need to call getTimer() after each iteration as well as the logic checks required to make sure we haven’t used up all the processing time in the frame. In most cases a 30% increase in processing time is a reasonable price to pay for maintaining  user interaction. You could even add a cancel button if you think it takes too long!

On a side note, I had a tough time coming up with a “fake” calculation to burden flash with. I ended up using the useless calculation below to simulate work which I think does a decent job. If you have a better idea please let me know!

var busyCalc:int = Math.sqrt(Math.random() * Math.random() * 1000.0);

This entry was posted on Thursday, November 11th, 2010 at 8:00 am and is filed under Actionscript, Flash. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.