Requirements

Prerequisite knowledge

Understanding of ActionScript and building Adobe AIR applications. Familiarity with Flash Builder.

User level

Beginning

The ActionScript bytecode generated by FlasCC delivers higher performance than the bytecode generated by the ActionScript compiler. Apart from the usage of better data types and instructions, FlasCC has the advantage of using domain memory which results in faster read/write access of the memory buffer. Flash and AIR Runtimes already support the special memory opcodes needed to use domain memory. The unavailability of a toolchain (Flash Builder, Flash Pro, AIR SDK) did not make it possible to use domain memory for creating .swf files. Beginning AIR 3.6, the ActionScript compiler (ASC2) also generates fast memory opcodes directly from the AS3 code (previously available only through FlasCC).
 
Note: The memory intrinsic APIs are available as part of the compiler (ASC2) package. To make use of the APIs, ensure that you use Flash Builder to build your applications. The compiler package with the APIs are not available for use in IDEs other than Flash Builder.
 
This article discusses the avm2.intrinsics.memory package and illustrates the speed enhancement achieved by using domain memory to store byte arrays.
 

 
Using the avm2.intrinsics.memory package

To enhance the speed of your byte array operations, assign the byte array to domain memory:
 
ApplicationDomain.currentDomain.domainMemory = myByteArray;
The avm2.intrinsics.memory package is available as part of the compiler. This package provides instructions for storing and loading data from the byte array stored in the domain memory.
 
Package avm2.intrinsics.memory { public function li8(addr:int):int; // load 8 bit int public function li16(addr:int):int; // load 16 bit int public function li32(addr:int):int; // load 32 bit int public function lf32(addr:int):Number; // load 32 bit float public function lf64(addr:int):Number; // load 64 bit float public function si8(value:int, addr:int):void; // store 8 bit integer public function si16(value:int, addr:int):void; // store 16 bit integer public function si32(value:int, addr:int):void; // store 32 bit integer public function sf32(value:Number, addr:int):void; // store 32 bit float public function sf64(value:Number, addr:int):void; // store 64 bit float public function sxi1(value:int):int; // sign extend a 1 bit value to 32 bits public function sxi8(value:int):int; // sign extend an 8 bit value to 32 bits public function sxi16(value:int):int; // sign extend a 16 bit value to 32 bits
When working with the memory intrinsic APIs, it would help to note that:
 
  • You can assign only one byte array at a time to domain memory.
  • You need to set the length of the byte array before assigning it to domain memory.
  • Using the load and store instructions directly, instead of using ActionScript wrapper functions, will deliver better performance.
  • You need to always assign the result of the load instruction to a variable. Not doing so results in a verify error which is currently a known bug.

 
ByteArray in domain memory versus a regular byte array

The following sample code depicts the regular usage of a byte array, and how operations on it can be made faster.
 
package { import flash.display.Sprite; import flash.system.ApplicationDomain; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.utils.ByteArray; import flash.utils.getTimer; import avm2.intrinsics.memory.li8; import avm2.intrinsics.memory.si8; public class DomainMemoryTest extends Sprite { private var BYTE_ARRAY_SIZE:Number = 10000000; private var resultsDisplay:TextField = new TextField(); private var normalByteArrayTime:uint = 0; private var fastByteArrayTime:uint = 0; public function DomainMemoryTest() { super(); setupDisplay(); timeNormalByteArray(); timeFastByteArray(); resultsDisplay.appendText("\nFast ByteArray is " + (normalByteArrayTime - fastByteArrayTime).toString() + " milliseconds faster."); } // Write and Read 'numInts' integers in/from the bytearray private function timeNormalByteArray() : void { var ba:ByteArray = new ByteArray(); var i:int = 0; var startTimer:int = getTimer(); for(i=0; i<BYTE_ARRAY_SIZE; i++) { ba.writeByte(100); } ba.position = 0; for(i=0; i<BYTE_ARRAY_SIZE; i++) { ba.readByte(); } var endTimer:int = getTimer(); normalByteArrayTime = endTimer - startTimer; resultsDisplay.appendText("Time to write and read normal ByteArray: " + normalByteArrayTime.toString()); } private function timeFastByteArray () : void { var ba:ByteArray = new ByteArray(); // Set the size of bytearray ba.length = BYTE_ARRAY_SIZE; ApplicationDomain.currentDomain.domainMemory = ba; var i:int = 0; var valueLoadedFromByteArray:int = 0; var startTimer:int = getTimer(); for(i=0; i<BYTE_ARRAY_SIZE; i++) { si8(100, i); } for(i=0; i<BYTE_ARRAY_SIZE; i++) { valueLoadedFromByteArray = li8(i); } var endTimer:int = getTimer(); fastByteArrayTime = endTimer - startTimer; resultsDisplay.appendText("\nTime to write and read fast ByteArray: " + fastByteArrayTime.toString()); } private function setupDisplay():void { resultsDisplay.x = 10; resultsDisplay.y = 10; resultsDisplay.border = true; resultsDisplay.multiline = true; resultsDisplay.wordWrap = true; resultsDisplay.autoSize = TextFieldAutoSize.LEFT; resultsDisplay.width = 400; addChild(resultsDisplay); } } }
The above snippet yields the following results:
 
  normal byte array fast byte array
Macbook Pro (2.6 GHz, 16GB) 3510 ms 1755 ms
iPhone 3GS
 
53600 ms 23800 ms
Using domain memory thus makes byte operations almost twice as fast as a regular byte array.
 

 
Where to go from here

For more information on Flash Builder, visit the Flash Builder documentation page.