Last Friday’s article expressed some longing for C-style function pointers. It attempted to use AS3’s Namespace class to fake a function pointer. Unfortunately, this resulted in far slower code than simple direct access. Today’s article shows a technique that actually results in far faster code!

The Namespace approach failed due to Namespace being a dynamic class and access through it therefore being necessarily slow. So how about a non-dynamic approach? The idea I came up with was to create a class like Java’s Runnable interface. The idea is to create an interface that defines one function that takes the parameters you want to pass and returns the parameters you want returned. This is similar to function pointers in C where the syntax forces you to specify what the function’s parameters and return value are. The next step is to create a class implementing the interface for each function you want to point to. Next, simply implement the one function that the interface specifies. Lastly, the code wanting to emulate function pointers points its Runnable variable at an appropriate object implementing Runnable and calls to its one function are then made. Consider this simple example:

package
{
	import flash.display.*;
	import flash.utils.*;
	import flash.text.*;
 
	public class RunnableTest extends Sprite
	{
		public function RunnableTest()
		{
			var logger:TextField = new TextField();
			logger.autoSize = TextFieldAutoSize.LEFT;
			addChild(logger);
 
			var i:int;
 
			const FUNC_CALL_REPS:int = 10000000;
			var runnable:Runnable = new MyRunnable();
			var func:Function = runnable.run;
			var beforeTime:int = getTimer();
			for (i = 0; i < FUNC_CALL_REPS; ++i)
			{
				func();
			}
			logger.appendText("Func call time: " + (getTimer()-beforeTime) + "\n");
			beforeTime = getTimer();
			for (i = 0; i < FUNC_CALL_REPS; ++i)
			{
				runnable.run();
			}
			logger.appendText("Runnable call time: " + (getTimer()-beforeTime) + "\n");
			beforeTime = getTimer();
			for (i = 0; i < FUNC_CALL_REPS; ++i)
			{
				this.foo();
			}
			logger.appendText("Direct call time: " + (getTimer()-beforeTime));
		}
 
		private function foo(): void
		{
		}
	}
}
internal interface Runnable
{
	function run(): void
}
internal class MyRunnable implements Runnable
{
	public function run(): void
	{
	}
}

The results are impressive:

Machine Function Object Time Runnable Time Direct Call Time
3.0 Ghz Intel Core 2 Duo with 2GB RAM on Windows XP 613 43 41
2.2 Ghz Intel Core 2 Duo with 2GB RAM on Mac OS X 10.6 828 63 59

It seems as though you sacrifice almost no performance using this technique. Runnables only slightly lag behind direct function calls and are some 14x faster than Function objects! But what else do you lose? Well, you’ll need to create at least one interface and two classes, which contributes to SWF size, project complexity, and number of files to maintain. You’ll need to create more classes implementing the interface if you have more functions to point at. You’ll also need to instantiate an object of each of these types in order to point at it. If you are going to do a lot of processing, this probably won’t be much of a burden for the benefits (fewer if-else chains) you’ll get. You can also pre-allocate and re-use them. Lastly, you’ll need to split these functions out of the classes they naturally belong in and therefore need to pass along the “this” pointer they would normally have and provide non-private access to the class as far as the function needs to do its work. This can lead to overexposed classes, but the internal access specifier can help with that.

There is one surprising benefit of the runnable strategy as described above. If you intend to pass the same arguments to the function over and over, such as the “this” pointer it would normally have, you can simply store them as fields of the class. This leads to a related secondary advantage. Say your function normally computed a value and added it to an Array field of the class it should belong to when not using the runnable technique. You could pass this Array to the runnable’s constructor, store it as a field, and then share a reference to the Array with the original class. Both of these are good for limiting argument passing.

This technique works out surprisingly well. It’s a lot of overhead in typing, propagation of files, and a little overhead in SWF size, but when you really need to eliminate some if-else chains with a function pointer-style solution, runnables sure seem to be the way to go.