Linked List Performance Test using Getter or Interface

Another test regarding linked lists. Since I heavily use interfaces within the frameworks I’m working on I tried to define interfaces for my linked list items. I would love to use an abstract interface but with the full linked list speed. Seems not possible. If you create an interface you need to use at least one getter function which kills performance.

I compared execution time using this code:

package
{
	import flash.utils.getTimer;
	import flash.events.Event;
	import flash.display.Sprite;
 
	public final class LinkedListPerformanceCheck extends Sprite
	{
		private var _firstItemWithPublicVar : ItemWithPublicVar;
		private var _firstFinalItemWithPublicVar : FinalItemWithPublicVar;
		private var _firstItemWithGetter : ItemWithGetter;
		private var _firstFinalItemWithGetter : FinalItemWithGetter;
		private var _firstIItemWithGetter : IItemWithGetter;
		private var _firstIFinalItemWithGetter : IFinalItemWithGetter;
 
		private var _c : int;
		private var _i : int;
 
		public function LinkedListPerformanceCheck()
		{
			loaderInfo.addEventListener( Event.COMPLETE, run );
		}
 
		private function run( event : Event ) : void
		{
			_c = 5000000;
			_i = 0;
			addEventListener( Event.ENTER_FRAME, onEnterFrame );
		}
 
		private function onEnterFrame( event : Event ) : void
		{
			switch( _i++ )
			{
				case 0 : createItemWithPublicVarTest(); break;
				case 1 : createFinalItemWithPublicVarTest(); break;
				case 2 : createItemWithGetterTest(); break;
				case 3 : createFinalItemWithGetterTest(); break;
				case 4 : createImplementedIItemWithGetterTest(); break;
				case 5 : createImplementedIFinalItemWithGetterTest(); break;
				case 6 : break; // wait
				case 7 : break; // wait
				case 8 : break; // wait
				case 9 : break; // wait
				case 10 : runItemWithPublicVarTest(); break;
				case 11 : runFinalItemWithPublicVarTest(); break;
				case 12 : runItemWithGetterTest(); break;
				case 13 : runFinalItemWithGetterTest(); break;
				case 14 : runImplementedIItemWithGetterTest(); break;
				case 15 : runImplementedIFinalItemWithGetterTest(); break;
				case 16 : runItemWithPublicVarTest(); break; // again - just to make sure...
				case 17 : runFinalItemWithPublicVarTest(); break; // again - just to make sure...
				default: removeEventListener( Event.ENTER_FRAME, onEnterFrame );
			}
		}
 
		private function createItemWithPublicVarTest() : void
		{
			var item : ItemWithPublicVar = _firstItemWithPublicVar = new ItemWithPublicVar();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ItemWithPublicVar(); }
		}
 
		private function runItemWithPublicVarTest() : void
		{
			var item : ItemWithPublicVar = _firstItemWithPublicVar;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runItemWithPublicVarTest( " +duration + " )");
		}
 
		private function createFinalItemWithPublicVarTest() : void
		{
			var item : FinalItemWithPublicVar = _firstFinalItemWithPublicVar = new FinalItemWithPublicVar();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new FinalItemWithPublicVar(); }
		}
 
		private function runFinalItemWithPublicVarTest() : void
		{
			var item : FinalItemWithPublicVar = _firstFinalItemWithPublicVar;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runFinalItemWithPublicVarTest( " +duration + " )");
		}
 
		private function createItemWithGetterTest() : void
		{
			var item : ItemWithGetter = _firstItemWithGetter = new ItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ItemWithGetter(); }
		}
 
		private function runItemWithGetterTest() : void
		{
			var item : ItemWithGetter = _firstItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runItemWithGetterTest( " +duration + " )");
		}
 
		private function createFinalItemWithGetterTest() : void
		{
			var item : FinalItemWithGetter = _firstFinalItemWithGetter = new FinalItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new FinalItemWithGetter(); }
		}
 
		private function runFinalItemWithGetterTest() : void
		{
			var item : FinalItemWithGetter = _firstFinalItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runFinalItemWithGetterTest( " +duration + " )");
		}
 
		private function createImplementedIItemWithGetterTest() : void
		{
			var item : IItemWithGetter = _firstIItemWithGetter = new ImplementedIItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ImplementedIItemWithGetter(); }
		}
 
		private function runImplementedIItemWithGetterTest() : void
		{
			var item : IItemWithGetter = _firstIItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runImplementedIItemWithGetterTest( " +duration + " )");
		}
 
		private function createImplementedIFinalItemWithGetterTest() : void
		{
			var item : IFinalItemWithGetter = _firstIFinalItemWithGetter = new ImplementedIFinalItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ImplementedIFinalItemWithGetter(); }
		}
 
		private function runImplementedIFinalItemWithGetterTest() : void
		{
			var item : IFinalItemWithGetter = _firstIFinalItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runImplementedIFinalItemWithGetterTest( " +duration + " )");
		}
	}
}
 
class ItemWithPublicVar { public var next : ItemWithPublicVar; }
 
final class FinalItemWithPublicVar { public var next : FinalItemWithPublicVar; }
 
class ItemWithGetter
{
	private var _next : ItemWithGetter;
	public function get next() : ItemWithGetter { return _next; }
	public function set next( value : ItemWithGetter ) : void { _next = value; }
}
 
final class FinalItemWithGetter
{
	private var _next : FinalItemWithGetter;
	public function get next() : FinalItemWithGetter { return _next; }
	public function set next( value : FinalItemWithGetter ) : void { _next = value; }
}
 
interface IItemWithGetter
{
	function get next() : IItemWithGetter;
	function set next( value : IItemWithGetter ) : void;
}
 
class ImplementedIItemWithGetter implements IItemWithGetter
{
	private var _next : IItemWithGetter;
	public function get next() : IItemWithGetter { return _next; }
	public function set next( value : IItemWithGetter ) : void { _next = value; }
}
 
interface IFinalItemWithGetter
{
	function get next() : IFinalItemWithGetter;
	function set next( value : IFinalItemWithGetter ) : void;
}
 
final class ImplementedIFinalItemWithGetter implements IFinalItemWithGetter
{
	private var _next : IFinalItemWithGetter;
	public function get next() : IFinalItemWithGetter { return _next; }
	public function set next( value : IFinalItemWithGetter ) : void { _next = value; }
}

Result:

LinkedListPerformanceCheck.runItemWithPublicVarTest( 86 )
LinkedListPerformanceCheck.runFinalItemWithPublicVarTest( 88 )
LinkedListPerformanceCheck.runItemWithGetterTest( 1247 )
LinkedListPerformanceCheck.runFinalItemWithGetterTest( 1148 )
LinkedListPerformanceCheck.runImplementedIItemWithGetterTest( 1161 )
LinkedListPerformanceCheck.runImplementedIFinalItemWithGetterTest( 1160 )
LinkedListPerformanceCheck.runItemWithPublicVarTest( 64 )
LinkedListPerformanceCheck.runFinalItemWithPublicVarTest( 62 )

Using public variables instead of getter functions is much faster. To make sure memory allocation doesn’t kill performance I repeated the public variables test at the end. Even faster.

Is there a way to define Interfaces for public variables?

Leave a Reply

Your email address will not be published. Required fields are marked *