Monday 26 May 2014

Static vs non-static: vars vs consts in Adobe AIR.

I was cleaning the engine that makes Beekyr a good performing game in all platforms. And I just thought , I could try to make it perform even more by converting my static classes and vars to non static.

I got the most bizarre results....

The tests consist in accessing a variable (or const) 1 million times.


Code:
package kaleidoEngine.parts.tests
{
    import citrus.core.CitrusEngine;
    import flash.display.Sprite;
    import flash.utils.getTimer;
    import game.GameVars;
    import game.Main;
    import kaleidoEngine.parts.data.EngineVars;
    /**
     * ...
     * @author Jaime Dominguez
     */
    public class staticPerformance extends Sprite
    {
        private var resultsProperties:Array;
        private var resultsStatics:Array;
        public var tempInt:int;
        public function staticPerformance()
        {
            testA(10000000);
            testB(10000000);
          
            row("*****END TEST*******");
          
        }
      
        private function testB(_REPS:Number):void
        {
            var _game:Main = CitrusEngine.getInstance() as Main;
            var beforeTime:int;
            var afterTime:int;
            var REPS:int = _REPS;
            var i:int;
            var inte:int;
            var c:Class;
            var num:Number;
          
            var resultA:int ;
            var resultB:int ;
      
            tempInt = GameVars.DIFFICULTY_LEVEL;
            var _tempInt:int = GameVars.DIFFICULTY_LEVEL;
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = GameVars.DIFFICULTY_LEVEL;
            }
            afterTime = getTimer();
            resultA = (afterTime-beforeTime);
            row("STATIC VAR INT:" + (afterTime-beforeTime))
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                inte = tempInt;
            }
            afterTime = getTimer();
            resultB = (afterTime-beforeTime);
            row("CLASS VAR INT:" +( afterTime-beforeTime))
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                inte = _tempInt;
            }
            afterTime = getTimer();
            resultB = (afterTime-beforeTime);
            row("FUNCTION CONST INT:" +( afterTime-beforeTime))
          
            if (resultA > resultB) row ("LOCAL VAR INT IS FASTER");
            else row ("NON-LOCAL VAR INT IS FASTER");
          
          
        }
      
        public function row(text:*):void {
            trace ("[TESTING] " + text);
        }
      
        public function testA(_REPS:uint):void{
          

            var _game:Main = CitrusEngine.getInstance() as Main;
            var beforeTime:int;
            var afterTime:int;
            var REPS:int = _REPS;
            var i:int;
            var inte:int;
            var c:Class;
            var num:Number;

            row("*****Testing ["+_REPS+"]*******");

            resultsProperties = new Array();
            resultsStatics = new Array();
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = _game.gameVars.CONST_NUM;
            }
            afterTime = getTimer();
            resultsProperties.push(afterTime-beforeTime)
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = _game.gameVars.CONST_INT;
            }
            afterTime = getTimer();
            resultsProperties.push(afterTime-beforeTime)
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = _game.gameVars.VAR_NUM;
            }
            afterTime = getTimer();
            resultsProperties.push(afterTime-beforeTime)

            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                inte = _game.gameVars.VAR_INT;
            }
            afterTime = getTimer();
            resultsProperties.push(afterTime-beforeTime)

            row ("------STATICS------");
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = GameVars.ST_CONST_NUM;
            }
            afterTime = getTimer();
            resultsStatics.push(afterTime-beforeTime);
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = GameVars.ST_CONST_INT;
            }
            afterTime = getTimer();
            resultsStatics.push(afterTime-beforeTime);
          
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                num = GameVars.ST_VAR_NUM;
            }
            afterTime = getTimer();
            resultsStatics.push(afterTime-beforeTime);
      
            beforeTime = getTimer();
            for (i = 0; i < REPS; ++i)
            {
                inte = GameVars.ST_VAR_INT;
            }
            afterTime = getTimer();
            resultsStatics.push(afterTime-beforeTime);
          
   
            //row("RESULTS :    PROPERTY   VS  STATIC ");
            //row("CONST NUM:" +resultsProperties[0] +" vs. " + resultsStatics[0] )
            if (resultsProperties[0] > resultsStatics[0]) row("CONST NUM: STATIC FASTER");
            else row("CONST NUM: PROPERTY FASTER");
            //row("-----------------");
            //row("CONST INT:" +resultsProperties[1] +" vs. " + resultsStatics[1] )
            if (resultsProperties[1] > resultsStatics[1]) row("CONST INT: STATIC FASTER");
            else row("CONST INT: PROPERTY FASTER");
            //row("-----------------");
            //row("VAR NUM:" +resultsProperties[2] +" vs. " + resultsStatics[2] )
            if (resultsProperties[2] > resultsStatics[2]) row("VAR NUM: STATIC FASTER");
            else row("VAR NUM: PROPERTY FASTER");
            //row("-----------------");
            //row("VAR INT:" +resultsProperties[3] +" vs. " + resultsStatics[3] )
            if (resultsProperties[3] > resultsStatics[3]) row("VAR INT: STATIC FASTER");
            else row("VAR INT: PROPERTY FASTER");
            //row("-----------------");

          
        }
    }

}


You will need to create a GameVars class to host all variables
And a _game class that has gameVars as GameVars


Results....

Test 1:

Int / Number (they take same time but only sometimes int is faster):

public const int : 7 ms; (this looks pretty fast!)
static public const int : 82 ms;


Number:
public var Number : 97 ms;
static public var Number : 86 ms;

Int:
public var int : 84 ms;
static public var int : 86 ms;


Test 2:        
If I copy a static var (int) to a local var int
static public var int : 89 ms (external to from that object)
public var int : 87 ms (class var)

 


So results are:
Test 1:
The fastest are NON-STATIC CONSTS

Test 2:
If copy static var to a local class or function var and then re-use that new var, makes a very little performance improvement... and only sometimes.

My conclusion is that only non-static consts are really fast. The rest are kind of the same.

Please do your tests and let us know, I'm not sure If I made some mistake because it makes little sense to me....




Tuesday 20 May 2014

Registering as Apple iOS Developer

Hello guys I went through hell of creating a new account , registering as iOS developer and setting up my first AIR app. So this steps are valid for Adobe AIR it might be useful for more people).

I was writing these steps while I was doing them but I did some wrong so I had to erase many steps and start again from some point....  I think I have fixed the list now.

You can follow the steps. If there is something wrong or missing, let me know.


  1. Make an apple account
  2. Register as developer
  3. Pay £60
  4. Wait for a bit.
  5. Get stuck in a loop. (I need to register but I am already registered)
  6. Ask for help? Doesn't work as I need a mac.
  7. Got a mac, carry on.
  8. [OSX] Create CSR: "certificateSigningRequest.certSigning" from KeyChain Access (MORE INFO HERE)
  9. [developer.apple.com] Create a certificate for 'iOS - App developent'. Uploading the file from previous step. And download the certificate file.
  10. [OSX] Convert it to P12 using the keychain access in OSX. (you will need this file when testing to the device and also you need another different P12 for publishing)
  11. [developer.apple.com] Create the app ID following these steps:http://www.adobe.com/devnet/air/articles/packaging-air-apps-ios.html
  12. [developer.apple.com] VERY IMPORTANT: DO NOT ADD THE PREFIX AIR. to the App ID. I found that in some websites and that is wrong.
  13. [iTunes software]. Connect the phone and copy de UID (click on serial number)
  14. [developer.apple.com] Register a new device.
  15. [developer.apple.com] Create a new provisioning Profile. Development for testing.
  16. [developer.apple.com] You will need to tick who's going to be testing and where. Then download a .mobileprovision file.
  17. [WINDOWS / OSX] Set up flash develop or whatever you use.
  18. Compile using Ad-Hoc or testing.



Wednesday 7 May 2014

How to implement FreshPlanet In App Purchase ANE in Adobe AIR

First thing I have to admit I went really crazy looking for solutions online, none of them were right.

I ended up inventing my own solution after being able to implement pozirks ANE successfully (for Android). I decided to use some stuff from here and there and I managed to make it work...

So here is the chest with the gold: here it goes what it's missing in all other pages that talk about this ANE.... The descriptor XML file configuration....


Application.XML file needs to have this lines among the rest of your items please place them in their own places:


<manifestAdditions>
<![CDATA[<manifest android:installLocation="preferExternal">
<uses-sdk android:minSdkVersion="8" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.vending.BILLING" />

<application android:enabled="true">
<activity android:name="com.freshplanet.inapppurchase.activities.BillingActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" android:background="#30000000" />
</application>
</manifest>]]>
</manifestAdditions>

and in extensions:
 
     
<extensionID> com.freshplanet.AirInAppPurchase </extensionID>
 


That works pretty well.
You should be able to make it work after this.... But if you have troubles , let me know and I will publish the .AS file using this ANE.