ActionScript 3 optimization techniques
hi all I have planned to start posting optimization techniques in couple of series. I will start first with showing you the techniques that Joa Ebert test work faster. Here you can find them
Me (Stanislav Stankov) growing up
hi all I have planned to start posting optimization techniques in couple of series. I will start first with showing you the techniques that Joa Ebert test work faster. Here you can find them
Testing environment
You will find many tables that covers execution time. All this are done on machine:
Comp1
Intel(R) Core(TM) Duo CPU E8400 @ 3000Hz 3.00 GHz, 3 .00 GB of RAM with Windows XP Professional SP3, Flash player version 9.0.115.0, NOT DEBUG PLAYERAll the tests were not done using the debug player and they were not running in debug mode which is very important in specific cases. Each test case was running ten times. The result shown is always the average execution time of the ten runs. This way two tests do not conflict with the garbage collection and each test is just responsible for its own memory usage. Before each run there is a ten seconds delay in order to not conflict with the Flash player starting procedure.
From result that using uint and int in loop did not make time difference. But I suggest you use where you can int instead of uint. You can find interesting article about (int vs uint vs Number) this topics here:
Avoid ints in ActionScript, by Sho Kuwamoto, date: June 15th, 2006
Types in AS3: ints not so fast, uints slow!, by Grant Skinner, date: June 15th, 2006
Use the Correct Type for the Job, by Think, date: June 20th, 2006
Optimization: When to do it., by Keith Peters, date: June 21st, 2006
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | package { import flash.display.Sprite; import flash.text.TextField; import flash.utils.getTimer; import flash.utils.setTimeout; import flash.system.Capabilities; [SWF(frameRate = '255')] public class TestCase extends Sprite { private static const n: int = 10000000; public function TestCase() { setTimeout(runTest, 10000); } private function runTest(): void { var a: Number = 0; for ( var i: int = 0; i < 10; ++i ) a += test06(); a /= 10; showResults(a); } private function showResults(result_:Number):void { var result_txt:TextField = new TextField(); result_txt.x = result_txt.y = 10; result_txt.width = 300; result_txt.text = "Iterations: [10^" + (String(n).length - 1) + "], int[ms]: " + result_ +"\nisDebugger: " + Capabilities.isDebugger + "\nversion: " + Capabilities.version; addChild(result_txt); } // 1. Iterations: [10^5], int[ms]: 4.7 // 2. Iterations: [10^5], int[ms]: 5 // 3. Iterations: [10^5], int[ms]: 4.4 // 4. Iterations: [10^5], int[ms]: 4.7 private function test00(): int { var startTime:int = getTimer(); //test start for (var i:int = 0; i < n; ++i ) { var a: Number = ( 1 as Number ); } //test end return (getTimer() - startTime); } // 1. Iterations: [10^5], int[ms]: 5.4 // 2. Iterations: [10^5], int[ms]: 5.2 // 3. Iterations: [10^5], int[ms]: 5.2 // 4. Iterations: [10^5], int[ms]: 5.4 private function test01(): int { var startTime:int = getTimer(); //test start for (var i:uint = 0; i < n; ++i ) { var a: Number = ( 1 as Number ); } //test end return (getTimer() - startTime); } // 1. Iterations: [10^7], int[ms]: 32.9 // 2. Iterations: [10^7], int[ms]: 33.1 // 3. Iterations: [10^7], int[ms]: 32.9 // 4. Iterations: [10^7], int[ms]: 33.4 private function test03(): int { var startTime:int = getTimer(); //test start var k:uint; for (var i:int = 0; i < n; ++i ) { k++; } //test end return (getTimer() - startTime); } // 1. Iterations: [10^7], int[ms]: 33 // 2. Iterations: [10^7], int[ms]: 32.8 // 3. Iterations: [10^7], int[ms]: 33 // 4. Iterations: [10^7], int[ms]: 32.8 private function test04(): int { var startTime:int = getTimer(); //test start var k:int; for (var i:int = 0; i < n; ++i ) { k++; } //test end return (getTimer() - startTime); } // 1. Iterations: [10^7], int[ms]: 91.8 // 2. Iterations: [10^7], int[ms]: 91.8 // 3. Iterations: [10^7], int[ms]: 91.7 // 4. Iterations: [10^7], int[ms]: 91.8 private function test05(): int { var startTime:int = getTimer(); //test start var k:int; for (var i:int = 0; i < n; ++i ) { k = (i + 15) / 7; } //test end return (getTimer() - startTime); } // 1. Iterations: [10^7], int[ms]: 91.8 // 2. Iterations: [10^7], int[ms]: 92.3 // 3. Iterations: [10^7], int[ms]: 92.2 // 4. Iterations: [10^7], int[ms]: 92.2 private function test06(): int { var startTime:int = getTimer(); //test start var k:uint; for (var i:int = 0; i < n; ++i ) { k = (i + 15) / 7; } //test end return (getTimer() - startTime); } } } |
I had to create Cross plot for one of my university exam (of Computer Aided Geometric Design). Here is little more info. Note that source files are available
Parametric Bezier curves are composed of coordinate functions: each component is a Bezier function. For two-dimensional curves, this can be used to construct the cross plot of curve. Image shows the decomposition of a Bezier curve into its two coordinate functions. A cross plot can be very helpful tool for the investigation not only of Bezier curves, but of general two-dimensional curves. We will use it for the analysis of Bezier and B-spline curves. It can be generalized to more then two dimensions, but is not as useful then.

Cross plot
You can see the example here.
Source files
info about program:

cross plot lines & symbols counter printscreen
Printscreen:

cross plot printscreen
Testing environment
You will find many tables that covers execution time. All this are done on machine:
Comp1
Intel(R) Core(TM) Duo CPU E8400 @ 3000Hz 3.00 GHz, 3 .00 GB of RAM with Windows XP Professional SP3, Flash player version 9.0.115.0, NOT DEBUG PLAYERAll the tests were not done using the debug player and they were not running in debug mode which is very important in specific cases. Each test case was running ten times. The result shown is always the average execution time of the ten runs. This way two tests do not conflict with the garbage collection and each test is just responsible for its own memory usage. Before each run there is a ten seconds delay in order to not conflict with the Flash player starting procedure.
From result we see that initializing objects and arrays with new constructor is slower then directly with {} and []. So it may be useful to keep in mind that when you creating objects or arrays use:
var array:Array = [];
var obj:Object = {};
instead of
var array:Array = new Array();
var obj:Object = new Object();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | package { import flash.display.Sprite; import flash.text.TextField; import flash.utils.getTimer; import flash.utils.setTimeout; import flash.system.Capabilities; [SWF(frameRate = '255')] public class TestCase extends Sprite { private static const n: int = 100000; public function TestCase() { setTimeout(runTest, 10000); } private function runTest(): void { var a: Number = 0; for ( var i: int = 0; i < 10; ++i ) a += test03(); a /= 10; showResults(a); } private function showResults(result_:Number):void { var result_txt:TextField = new TextField(); result_txt.x = result_txt.y = 10; result_txt.width = 300; result_txt.text = "Iterations: [10^" + (String(n).length - 1) + "], int[ms]: " + result_ +"\nisDebugger: " + Capabilities.isDebugger + "\nversion: " + Capabilities.version; addChild(result_txt); } // 1. Iterations: [10^5], int[ms]: 28.6 // 2. Iterations: [10^5], int[ms]: 28.7 private function test00(): int { var startTime:int = getTimer(); //test start for (var i:int = 0; i < n; ++i ) { var obj:Object = new Object(); } //test end return (getTimer() - startTime); } // 1. Iterations: [10^5], int[ms]: 22.1 // 2. Iterations: [10^5], int[ms]: 22.1 // 3. Iterations: [10^5], int[ms]: 22.6 private function test01(): int { var startTime:int = getTimer(); //test start for (var i:int = 0; i < n; ++i ) { var obj:Object = { }; } //test end return (getTimer() - startTime); } // 1. Iterations: [10^5], int[ms]: 58.8 // 2. Iterations: [10^5], int[ms]: 58.8 private function test02(): int { var startTime:int = getTimer(); //test start for (var i:int = 0; i < n; ++i ) { var array:Array = new Array(); } //test end return (getTimer() - startTime); } // 1. Iterations: [10^5], int[ms]: 23.7 // 2. Iterations: [10^5], int[ms]: 24 // 3. Iterations: [10^5], int[ms]: 23.6 private function test03(): int { var startTime:int = getTimer(); //test start for (var i:int = 0; i < n; ++i ) { var obj:Array = []; } //test end return (getTimer() - startTime); } } } |
Actionscript3 & PHP & MySQL & XML
I’m gonna post series of tutorials:
Getting data from XML, AS3
Getting data from MySQL, AS3 + PHP + MySQL file
Uploading file with AS3 + PHP
Send email with AS3 + PHP
How to parse a simple XML file. This is our structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="utf-8" ?> <data> <users> <user> <id>18</id> <name>bobanman</name> <avatar><![CDATA[]]></avatar> <registerData>13-07-2008</registerData> <email>bobanman@msn.com</email> </user> <user> <id>20</id> <name>ilya</name> <avatar><![CDATA[]]></avatar> <registerData>15-07-2008</registerData> <email>ilya@asymmetric.co.il</email> </user> </users> </data> |
First we will build XML parser. This is my favorite ways to parse it like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // parce XML private function parseXML($rawData_:String):void { var xmldoc:XMLDocument = new XMLDocument(); xmldoc.ignoreWhite = true; xmldoc.parseXML($rawData_); var out:Array = []; const imax:int = xmldoc.firstChild.firstChild.childNodes.length; for (var i:int = 0; i < imax; i++ ) { //collect data from XML out[i] = getUserDTO(xmldoc.firstChild.firstChild.childNodes[i]); } // all user data goes here :) trace(out); } // create UserDTO from XMLNode private function getUserDTO($xmlNode_:XMLNode):UserDTO { return new UserDTO(int(XMLNode($xmlNode_.childNodes[0]).firstChild.toString()), XMLNode($xmlNode_.childNodes[1]).firstChild.toString(), XMLNode($xmlNode_.childNodes[2]).firstChild.toString(), XMLNode($xmlNode_.childNodes[3]).firstChild.toString(), XMLNode($xmlNode_.childNodes[4]).firstChild.toString()); } |
You can also parse it using XML class, but like I say I prefer to do it this way
so with this script we will retrieve all the data from XML file.
This is one way also to get data from DB, create with server side language xml files like this and to parce them. Other options are AMFPHP or ASQL but we will cover these two in future topics.
So the we have to load the XML and get set all data into lets say array object.
So full script goes like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package { import flash.display.Sprite; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; import flash.xml.XMLDocument; import flash.xml.XMLNode; [SWF(frameRate = '30')] public final class DocumentClass extends Sprite { public function DocumentClass():void { loadXML(); } // load external XML private function loadXML():void { var ulloader:URLLoader = new URLLoader(new URLRequest("data.xml")); ulloader.addEventListener(Event.COMPLETE, completeHandler); } // parce XML private function parseXML($rawData_:String):void { var xmldoc:XMLDocument = new XMLDocument(); xmldoc.ignoreWhite = true; xmldoc.parseXML($rawData_); var out:Array = []; const imax:int = xmldoc.firstChild.firstChild.childNodes.length; for (var i:int = 0; i < imax; i++ ) { //collect data from XML out[i] = getUserDTO(xmldoc.firstChild.firstChild.childNodes[i]); } // all user data goes here :) trace(out); } // create UserDTO from XMLNode private function getUserDTO($xmlNode_:XMLNode):UserDTO { return new UserDTO(int(XMLNode($xmlNode_.childNodes[0]).firstChild.toString()), XMLNode($xmlNode_.childNodes[1]).firstChild.toString(), XMLNode($xmlNode_.childNodes[2]).firstChild.toString(), XMLNode($xmlNode_.childNodes[3]).firstChild.toString(), XMLNode($xmlNode_.childNodes[4]).firstChild.toString()); } // exterenal xml loaded. Parse it then private function completeHandler(info:Event):void { info.target.removeEventListener(Event.COMPLETE, completeHandler); parseXML(info.target.data); } } } |
class UserDTO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package { public final class UserDTO { private var _id:int; private var _name:String; private var _avatarURL:String; private var _regDate:String; private var _email:String; public function UserDTO($id_:int, $name_:String, $avatarURL_:String, $regDate_:String, $email_:String):void { _id = $id_; _name = $name_; _avatarURL = $avatarURL_; _regDate = $regDate_; _email = $email_; } public function get id():int { return _id; } public function get name():String { return _name; } public function get avatarURL():String { return _avatarURL; } public function get regDate():String { return _regDate; } public function get email():String { return _email; } public function toString():String { return "[ UserDTO id='" + _id + "' name='" + _name + "' avatarURL='" + _avatarURL + "' regDate='" + _regDate + "' email='" + _email + "' ]"; } } } |
So now lets create PHP file that give us the date from MySQL with same structure.
Getting data from Mysql, AS3 + PHP + MySQL file
more about this error 5005: Unknown error optimizing byte code
Solving:
1. my computer -> properties -> advanced -> environment vars -> then make a new var like this:
JAVA_TOOL_OPTIONS
-Xmx256M
2. File >> Save and Compact
3. Close Flash,
4. Open Flash
Compile worked
Sort array by properties ID. Array have only VideoDTO objects.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var data_arr:Array = []; var k:int = 0; while ( k < 20) { data_arr[k] = new VideoDTO(String(Math.random()*5),Math.random()*10+5,"img","title"); trace(data_arr[k]); k++; } data_arr.sortOn("ID", [Array.NUMERIC]); trace("==============="); k = 0; while ( k < 20) { trace(data_arr[k]); k++; } |
VideoDTO class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | package { public final class VideoDTO { private var _id:String; private var _engine:int; private var _imageURL:String; private var _title:String; private var _duration:int; private var _views:int; private var _rating:Number; /*------------------------------------ Constructor ------------------------------------*/ public function VideoDTO($id_:String, $engine_:int, $imageURL_:String, $title_:String = "", $duration_:int = -1, $views_:int = -1, $rating_:Number = -1):void { _id = $id_; _engine = $engine_; _imageURL = $imageURL_; _title = $title_; _duration = $duration_; _views = $views_; _rating = $rating_; } /*------------------------------------ Public methods ------------------------------------*/ public function duplicate():VideoDTO { return new VideoDTO(_id, _engine, _imageURL, _title, _duration, _views, _rating); } public function get ID():String { return _id; } public function get engine():int { return _engine; } public function get imageURL():String { return _imageURL; } public function get title():String { return _title; } public function get duration():int { return _duration; } public function get views():int { return _views; } public function get rating():Number { return _rating; } public function toString():String { return "[ VideoDTO id='" + _id + "' title='" + _title + "' engine='" + _engine + "' imageURL='" + _imageURL + "' duration='" + _duration + "' views='" + _views + "' ]"; } public function dtoDestroy():void { trace("destroy VideoDTO = " + _title); _id = null; _engine = 0; _imageURL = null; _title = null; _duration = 0; _views = 0; _rating = 0; } } } |