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:
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.
Comments (2)
Hi,
nice comparaison, thanks. I posted your results on my blog (french):
http://www.flex-tutorial.fr/2010/07/18/adobe-alchemy-comparaison-de-performances-sur-algorithme-de-tri-actionscript-c/
Fabien
http://www.flex-tutorial.fr
Posted by Adobe Flex Tutorial | July 18, 2010 5:15 PM
Posted on July 18, 2010 17:15
Great one.
Thanks for sharing it.
Posted by Chintan Kotadia | August 25, 2010 8:03 PM
Posted on August 25, 2010 20:03