« Managing Java Http sessions in GAE applications | Main | Fixing the horizontal scroll for the Flex Text Highlighter Class »

Adobe Alchemy: a comparative example

In my last post I introduced the Alchemy Project and I explained how to install/set up the Alchemy environment on a Window machine to compile a very simple "c" file in a swc.
Today I'll go deeper and talk about Alchemy through a comparative example: Alchemy aimes to allow users to take advantage of efficient C/C++ (existing or not) designed to accomplish very cpu-intensive tasks. The performance improvements of flex applications can be very significant e I'll try to give you a sample, with a simple test: I've implemented an inefficient and decidedly didactic ordering algorithm, the BubbleSort, either in Actionscript and in C/Alchemy. Then I've tested both implementation to order an actionscript reverse ordered array of integers with 20,000 elements(the worst case for the bubblesort algorithms).

Here is the Actionscript implementation:

public function bubbleSort(array:Array):void
{
	var temp:int = 0;
	var alto:int = array.length;
	while(alto > 0)
	{
		for(var i:int = 0; i<alto; i++)
		{
			if(array[i] > array[i+1])
			{
				temp = array[i];
				array[i] = array[i+1];
				array[i+1] = temp;
			}
		}
		alto--;
	} 
}

and here I show you the C implementation

void BubbleSort(int *array, int array_size)
{
   
  int i, tmp;
  int bound = array_size; 
 
  while (bound > 1)
  {
	for (i=0; i<bound-1; i++)
    {
        if (array[i] > array[i+1]) 
        { 
			tmp = array[i]; 
            array[i] = array[i+1]; 
            array[i+1] = tmp;
        } 
    }
    bound--; 
  }
}

Unfortunately I couldn't use the C implementation as it is. I needed to write some more code using Alchemy actionscript/C Api to realize the translation of the Actionscript array to the C integer array data structure:

#include <stdlib.h>
#include <stdio.h>
 
//Header file for AS3 interop APIs
//this is linked in by the compiler (when using flaccon)
#include "AS3.h"
 
//INSERT HERE THE C IMPLEMENTATION OF THE BUBBLESORT ALGORITHM
 
static AS3_Val orderArray(void* self, AS3_Val args)
{
	//Creating a C representation of the Actionscript Array object
	AS3_Val actionscript_array = NULL;
	AS3_ArrayValue( args, "AS3ValType", &actionscript_array );
	 
	/*
	 *         Translation process from Actionscript to C in 4 steps:
	 */
	//STEP 1 : calculating the dimension of the Actionscript array
	AS3_Val actionscript_array_size =  AS3_GetS(actionscript_array, "length");
	int array_size = AS3_IntValue(actionscript_array_size);
 	
	//STEP 2: declaring the C array to use with BubbleSort
	int array_c[array_size];
 	
	//STEP 3 : ActionScript function pop() of Array Class
	AS3_Val pop_function = AS3_GetS(actionscript_array, "pop");
	AS3_Val emptyParams = AS3_Array("");
 	
	//STEP 4(iterative): Extracting the actionscript integer values from the actionscript array
	//and storing them into the c array
	int i = 0;
	for(i = array_size-1; i >= 0 ; i--)
	{
		AS3_Val temp_actionscript_Int = AS3_Call(pop_function, actionscript_array, emptyParams);
		int tmp = AS3_IntValue(temp_actionscript_Int);
		array_c[i] = tmp;
		AS3_Release(temp_actionscript_Int);
	}
	AS3_Release(pop_function);
	/*
	 *   END of Translation process from actionscript to C
	 */
 	
	/*
	 *      Ordering operations: invoking the Bubble Sort on the c array of integers
	 */
	BubbleSort(array_c, array_size);
 	
	/*
	 *         Translation process from C to actionscript:
	 */
 	 
	//ActionScript function push() of Array Class
	AS3_Val push_function = AS3_GetS(actionscript_array, "push");
 	
	//Storing the ordered integer values into a new actionscript array object
	int j;
	for( j = 0; j < array_size ; j++)
	{
		AS3_Val int_to_push = AS3_Array("IntType", array_c[j]);
		AS3_Call(push_function, actionscript_array, int_to_push );
		AS3_Release(int_to_push);
	}
	AS3_Release(push_function);
 	
	return actionscript_array;
	/*
	 *   END of Translation process from C  to actionscript
	 */
}
 
//entry point for code
int main()
{
	//define the methods exposed to ActionScript
	//typed as an ActionScript Function instance
	AS3_Val orderArrayMethod = AS3_Function( NULL, orderArray );
 
	// construct an object that holds references to the functions
	AS3_Val result = AS3_Object( "orderArray: AS3ValType", orderArrayMethod );
 
	// Release
	AS3_Release( orderArrayMethod );
 
	// notify that we initialized -- THIS DOES NOT RETURN!
	AS3_LibInit( result );
 
	// should never get here!
	return 0;
}

As a consequence, when analyzing the test results, we have to consider the extra work the C/Alchemy implementation of the algorithm did to realize the ordering task.

To compile the previous code follow the instruction I showed in this post
to obtain a file .swc you can use in a flex test application as I did in may test example.

Here the code of my flex test application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" creationComplete="init();">
	
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			
			import cmodule.bubblesort.CLibInit;			
			
			private var startDate:Date;
			private var stopDate:Date;
			
			private function init():void
			{
				
				this.addEventListener("actionscriptSortComplete",handler);
				this.addEventListener("cSortComplete",handler);
				var intArray:Array = new Array();
				var intArray2:Array = new Array();
				for(var i:int = 20000; i > 0; i--)
				{
					intArray.push(i);
					intArray2.push(i);
				}
				list.dataProvider = intArray;
				list2.dataProvider = intArray2;
			}
			
			
			//INSERT HERE THE CODE OF THE ACTIONSCRIPT IMPLEMENTATION OF BUBBLESORT ALGORTHM
			
			public function orderArray(event:Event):void
			{
				startDate = new Date;
				
				if(event.target.id == "actionscriptOrderingButton" )
				{
					var source1:Array = (list.dataProvider as ArrayCollection).source;
					bubbleSort(source1);
					this.dispatchEvent(new Event("actionscriptSortComplete"));
				}
				else
				{
					var loader:CLibInit = new CLibInit();
					var lib:Object = loader.init();
					var source2:Array = (list2.dataProvider as ArrayCollection).source;
					list2.dataProvider = lib.orderArray(source2);
					this.dispatchEvent(new Event("cSortComplete"));
				}
				
				
			}
			
			public function handler(event:Event):void
			{
				stopDate = new Date();
				var diff:Number = stopDate.getTime() - startDate.getTime();
				if(event.type == "actionscriptSortComplete")
				{
					timeLabel.text = "time elapsed : "+diff/1000+" sec!";
					(list.dataProvider as ArrayCollection).refresh();
				}
				else
				{
					timeLabel2.text = "time elapsed :"+diff/1000+"sec!";
					(list2.dataProvider as ArrayCollection).refresh();
				}
				
			}
			
		]]>
	</mx:Script>
	
	<mx:List id="list" width="30%"  />
	<mx:VBox>
		<mx:Button id="actionscriptOrderingButton" label="Actionscript BubbleSort" click="orderArray(event);"  />
		<mx:Label id="timeLabel" text="..." />
	</mx:VBox>
	<mx:List id="list2" width="30%"/>
	<mx:VBox>
		<mx:Button id="cOrderingButton" label="C BubbleSort" click="orderArray(event);"  />
		<mx:Label id="timeLabel2" text="..." />
	</mx:VBox>
	<mx:Label id="lb2" text="" />
	
	
</mx:Application>

And here are some screenshots of the results obtained by the test application:
test-actionscriptbubblesort.PNG

test-cbubblesort.PNG

To order an array of 20,000 integers in the worst case:
- the actionscript algorithm spent : 32.031 sec
- the Alchemy/C algorithm spent : 7 sec
Using the Alchemy/C implementation of bubblesort I got an improvement in speed of about 75%.
This is certainly an encouraging result and an evidence that Alchemy can be exploited by developers to improve performance of the most intensive task executed by their flex application.

TrackBack

TrackBack URL for this entry:
http://blog.comtaste.com/mt-tb.cgi/124

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)

About

This page contains a single entry from the blog posted on July 12, 2010 4:36 PM.

The previous post in this blog was Managing Java Http sessions in GAE applications.

The next post in this blog is Fixing the horizontal scroll for the Flex Text Highlighter Class.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type 3.33