Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - hansbe

Pages: 1
1
The content of this post shows how to do some rudimentary profiling, that is, how to figure out how much time a piece of code takes. The basic idea presented here is to use a stopwatch method:
  • Measure the current system time (tic)
  • Execute code under test
  • Measure the current system time (toc)
  • Present the measurement result (toc-tic)

I only use stencyl for flash, but if anyone posts a method for iOS, I can update this post.

Flash AS3 method
The basic idea is to use the flash.utils.getTimer() method which reports time since a flash application started in milliseconds. Unfortunately I know of no more accurate timer in flash, therefore it will be necessary to wrap most bits of code in a loop to test it.

    Step 1 : Put this in a code block at the beginning of the behavior/script/class:
    [/list]
    Code: [Select]
    import flash.utils.getTimer;
    var tic,toc : int;
    Step 2 : Do a tic measurement and wrap the code you want to test in a loop.
    Code: [Select]
    tic = flash.utils.getTimer();
    for(var index0:int = 0; index0 < 10000; index0++)
    {
    Step 3 : End the loop, do a toc measurement and print.
    Code: [Select]
    }
    toc = flash.utils.getTimer();
    print("[loop] time taken:"+(toc-tic));
    Interpreting results:
    • Results vary linearly from CPU to CPU based on operating frequency.
    • Results can vary a LOT from CPU to CPU based on architecture (pipelining, branch prediction).
    • If the code is 'memory intensive' the size of the cache is important, as well as the speed of memory retrievial itself.
    • GPU capabilities and similar can also affect results a lot, for rendering, etc.

    Flash AS3 Examples:

    My laptop CPU runs at 2.26 GHz
    An empty loop with 10 million iterations took about 43 ms on average. Indicating that each iteration took on average: (0.043/10000000)*2260000000 ~= 9.73 cycles.
    (This isn't entirely accurate of course. The most important source of error is that the code may be interrupted by other tasks by the operating system.)

    A loop containing 'foo=foo+1;' with 10 million iterations took about 1018 ms on average. Indicating that each iteration took on average: (1.018/10M)*2260M = 230 cycles.
    A loop containing 100 'foo=foo+1;' with 100k iterations took about 430 ms on average. Indicating that each iteration took on average: (0.430/0.1M)*2260M = 9718 cycles.
    However each instruction took on average: 9718/100 ~= 9.7 cycles.

    This performance is pretty nasty (bad) and I the issue probably with pipelining. E.g. for the foo=foo+1; instruction my cpu must wait until foo in the previous instruction is calculated before starting on the next instruction.

    A loop containing 10 repeated calls to 'foo2();' where foo2() is an empty function (custom event) with 33k iterations took about 10 ms. Indicating that each function call took on average: (0.010/0.033M)*2260M ~= 684 cycles.

    Some possible performance hogs

    • You don't want these inside inner loops (so they execute many many times)

    A loop containing 2 game text attribute setters;'. I.e.:
    Code: [Select]
    setGameAttribute("gaText", "cba");
    setGameAttribute("gaText", "abc");
    with 100k iterations took about 77 ms. Indicating that each setter call took: (0.077/0.1M)*2260M/2 ~= 870 cycles.

    A loop containing 2 behavior boolean attribute setters;'. I.e.:
    Code: [Select]
    _Collided = false;
    propertyChanged("_Collided", _Collided);
    _Collided = true;
    propertyChanged("_Collided", _Collided);
    with 100k iterations took about 128 ms. Indicating that each behavior setter call took: (0.128/0.1M)*2260M/2 ~= 1446 cycles.
    (It is obviously the call to propertyChanged that takes so much time, and it is likely not neccessary inside an inner loop. (Note to self:There were 12 other attributes in this behavior.))

    An obvious optimization is to remove propertyChanged(). I believe it is unneccessary unless you use attribute listeners. It might be a mistake of the code generation to generaty this code bit for all attribute setters.
    Now I also hypothesize without testing that the dynamics of setGameAttribute() and propertyChanged() can change according to how many attributes you have. So if you have many game attributes,  behavior attributes could be faster. Re. Tom in this post.


    I hope this can lead people to experiment, discuss, and from that understand a little bit about how to write faster code. If you share experiences I can try to summarize results in this first post, from time to time.

    2
    Ok, so now I've made my first short game, It's not fantastic but kind of cute (?). I've put it on kongregate and stencyl arcade a few minutes ago.

    My question now is... Will it be worth it trying to monetize on this with ads?

    If I want to use MochiADs I should go Pro, but how much money would it bring me ?
    More than the $200 I would put out ?

    If you have any experience in doing this, please let me know what you think what my game might bring of income, here:
    http://community.stencyl.com/index.php/topic,10915.msg65758.html#msg65758
    or here: http://www.kongregate.com/games/hansbe/run-gemmy-run

    3
    I'm using stencyl 2.1 on Win XP.

    Something happened after I renamed my game. I'll just say what I did first:
     * I renamed my game, then after closing I chose to save. Both the old game and new game was then present.
     * I closed and reopened stencyl, and I decided to rename the new game again.

    When I test my game now something has happened, definitively to the ActorEvents, perhaps with other things as well (# of things its counting through has gone down from 133 to 95).
    What happens when I test the game is that the events don't react so they are probably not loaded.

    When I look into data.xml on the actor for the actorevent in question I find this:
    Code: [Select]
    <actor adamp="0.0" ascale="true" atlasID="0" bodytype="2" continuous="true" desc="" eventsnippetid="338" fixedrot="false" fric="0.2" gid="3" id="636" ignoreg="false" inertia="1.0" ldamp="0.0" lw="false" mass="1.0" name="man_instr" oid="-1" pausable="true" rest="0.0" shared="false" sprite="637" static="false" touchable="true">
            <snippets/>
        </actor>

    What more, ActorEvents_636.design exists and contains the correct event.
    The events are there and everything seems fine when I view it in Stencyl ...
    The ActorEvents_636.as script is also correctly in the export folder ...

    One thing that's been annoying me earlier with this scene is how stencyl keeps reverting some changes after i close a game.

    I managed to recover from the whole thing by deleting the actor for which the event wasnt working, then adding the actor again. Since I had been looking at the scene xml (9.xml in this case). I noticed that the codes changed from something like (i dont remember the exact actor values but there was an empty snippet or snippets node):
    Code: [Select]
    <actor a="0.0" aid="5" c="false" group="3" id="636" name="man_instr 5" sx="1.0" sy="1.0" x="183" y="101" z="1">
       <snippet/>
    </actor>
    to
    Code: [Select]
    <actor a="0.0" aid="5" c="false" group="3" id="636" name="man_instr 5" sx="1.0" sy="1.0" x="183" y="101" z="1"/>

    My theory now is the empty node might have caused the issue ? 

    Anyway, I fixed the obvious thing that was broken in my game, but maybe I have more errors, and it's not obvious to me what happened or even when.

    I have a feeling somethings messed up with how/where stencyl uses temporary files or memory when closing&saving games, which it does really often. One thing that has been bugging me with this particular scene and actor before is that I change the rotation angle, and move it, and everything works fine, until I close my game and I choose to save. Then stencyl overwrites my changes with what it was prior to my changes...

    Also possibly important: Another thing crashed Stencyl (after I had this error, while I was hunting this bug): I managed to click test game twice rather quickly and it kind of occupied all resources on my computer for over a minute before I killed it...

    4
    Old Bugs (1.x/2.x) / Performance hit
    « on: May 25, 2012, 04:12:56 am »
    I've tested the below with a new game (see next post). It might not be related to collisions, but it's still quite an impact in terms of performance.

    ---

    I tested this with the new 2.1 version:

    I have one scene with N actors, type sensor.

    When I increase the amount of actors of a group the flixel engine uses linearly more time to detect collisions.

    Also when I enable or disable the test collision group against itself there is no change in the time flixel uses. So it seems a collision group is always tested against itself?

    This might be related to that the game I'm using was originally created in 2.0, but I don't have time to test a enw game right now, maybe later.


    5
    Windows / Mac / Flash / HTML5 / Run Gemmy! Run! (formerly KO)
    « on: May 24, 2012, 06:02:27 am »
    This platformer is intended to be a mini-platforming/race-game you complete in a ca. 5 minute run, although you might not make it on the first run ... You collect 150 gems and get to the flag within the time, score is based on completion time and lives lost.

    Play now: http://www.stencyl.com/game/play/12780

    Edits:
     - I've changed the name of the game from the non-descriptal KO to Run Gemmy! Run!

    6
    I've made a behaviour and put it on forge in the 'Custom Gradient Test Game'. It's flash only.

    The gradient is a bit slower than the built-in, but you can do vertical/horizontal gradients and it features blending modes, and opacity, so you can get some interesting results if you overlay it with the default.

    You can also tile an actor (not animated) with blending modes. For the actor background you can have parallax combined with velocity so you can make simple wind, steam, etc. effects (they aren't perfect but still nice).

    This is the first time I code in flash as3, so if anyone with experience see something I do wrong, please let me know. Also I'm interested to know if the framerates are good.



    7
    When trying to refresh attributes it fails if I use Vector.<uint> in the code. E.g.:

    Code: [Select]
    50: private var colorindex, alphaindex : Vector.<uint>;
    The log reports the line number with error:
    Code: [Select]
    uk.co.badgersinfoil.metaas.SyntaxException: Unexpected token LT at line 50
    at uk.co.badgersinfoil.metaas.impl.ASTUtils.buildSyntaxException(ASTUtils.java:224)
    at uk.co.badgersinfoil.metaas.impl.ASTActionScriptParser.parse(ASTActionScriptParser.java:37)
    at stencyl.sw.app.tasks.BuildOneTask.annotate(BuildOneTask.java:338)
    at stencyl.sw.app.tasks.BuildOneTask.<init>(BuildOneTask.java:66)
    at stencyl.sw.editors.snippet.code.SnippetPanel.processAnnotations(SnippetPanel.java:431)
    at stencyl.sw.editors.snippet.code.SnippetPanel.actionPerformed(SnippetPanel.java:298)
    at stencyl.sw.actions.SAction.actionPerformed(SAction.java:119)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    Caused by: NoViableAltException(139!=[1184:1: ident : ( IDENT | i= USE -> IDENT[$i] | i= XML -> IDENT[$i] | i= DYNAMIC -> IDENT[$i] | i= NAMESPACE -> IDENT[$i] | i= IS -> IDENT[$i] | i= AS -> IDENT[$i] | i= GET -> IDENT[$i] | i= SET -> IDENT[$i] );])
    at org.asdt.core.internal.antlr.AS3Parser.ident(AS3Parser.java:16613)
    at org.asdt.core.internal.antlr.AS3Parser.qualifiedIdent(AS3Parser.java:9046)
    at org.asdt.core.internal.antlr.AS3Parser.propOrIdent(AS3Parser.java:15289)
    at org.asdt.core.internal.antlr.AS3Parser.identifier(AS3Parser.java:8160)
    at org.asdt.core.internal.antlr.AS3Parser.typeExpression(AS3Parser.java:8000)
    at org.asdt.core.internal.antlr.AS3Parser.variableDeclarator(AS3Parser.java:3082)
    at org.asdt.core.internal.antlr.AS3Parser.variableDefinition(AS3Parser.java:2912)
    at org.asdt.core.internal.antlr.AS3Parser.typeBlockEntry(AS3Parser.java:2179)
    at org.asdt.core.internal.antlr.AS3Parser.typeBlock(AS3Parser.java:2002)
    at org.asdt.core.internal.antlr.AS3Parser.classDefinition(AS3Parser.java:1326)
    at org.asdt.core.internal.antlr.AS3Parser.packageBlockEntry(AS3Parser.java:1037)
    at org.asdt.core.internal.antlr.AS3Parser.packageBlock(AS3Parser.java:809)
    at org.asdt.core.internal.antlr.AS3Parser.packageDecl(AS3Parser.java:742)
    at org.asdt.core.internal.antlr.AS3Parser.as3CompilationUnit(AS3Parser.java:635)
    at org.asdt.core.internal.antlr.AS3Parser.compilationUnit(AS3Parser.java:369)
    at uk.co.badgersinfoil.metaas.impl.ASTActionScriptParser.parse(ASTActionScriptParser.java:35)
    ... 42 more
    uk.co.badgersinfoil.metaas.SyntaxException: Unexpected token LT at line 50
    at uk.co.badgersinfoil.metaas.impl.ASTUtils.buildSyntaxException(ASTUtils.java:224)
    at uk.co.badgersinfoil.metaas.impl.ASTActionScriptParser.parse(ASTActionScriptParser.java:37)
    at stencyl.sw.app.tasks.BuildOneTask.annotate(BuildOneTask.java:338)
    at stencyl.sw.app.tasks.BuildOneTask.<init>(BuildOneTask.java:66)
    at stencyl.sw.editors.snippet.code.SnippetPanel.processAnnotations(SnippetPanel.java:431)
    at stencyl.sw.editors.snippet.code.SnippetPanel.actionPerformed(SnippetPanel.java:298)
    at stencyl.sw.actions.SAction.actionPerformed(SAction.java:119)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.awt.EventQueue$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.awt.EventQueue$2.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    Caused by: NoViableAltException(139!=[1184:1: ident : ( IDENT | i= USE -> IDENT[$i] | i= XML -> IDENT[$i] | i= DYNAMIC -> IDENT[$i] | i= NAMESPACE -> IDENT[$i] | i= IS -> IDENT[$i] | i= AS -> IDENT[$i] | i= GET -> IDENT[$i] | i= SET -> IDENT[$i] );])
    at org.asdt.core.internal.antlr.AS3Parser.ident(AS3Parser.java:16613)
    at org.asdt.core.internal.antlr.AS3Parser.qualifiedIdent(AS3Parser.java:9046)
    at org.asdt.core.internal.antlr.AS3Parser.propOrIdent(AS3Parser.java:15289)
    at org.asdt.core.internal.antlr.AS3Parser.identifier(AS3Parser.java:8160)
    at org.asdt.core.internal.antlr.AS3Parser.typeExpression(AS3Parser.java:8000)
    at org.asdt.core.internal.antlr.AS3Parser.variableDeclarator(AS3Parser.java:3082)
    at org.asdt.core.internal.antlr.AS3Parser.variableDefinition(AS3Parser.java:2912)
    at org.asdt.core.internal.antlr.AS3Parser.typeBlockEntry(AS3Parser.java:2179)
    at org.asdt.core.internal.antlr.AS3Parser.typeBlock(AS3Parser.java:2002)
    at org.asdt.core.internal.antlr.AS3Parser.classDefinition(AS3Parser.java:1326)
    at org.asdt.core.internal.antlr.AS3Parser.packageBlockEntry(AS3Parser.java:1037)
    at org.asdt.core.internal.antlr.AS3Parser.packageBlock(AS3Parser.java:809)
    at org.asdt.core.internal.antlr.AS3Parser.packageDecl(AS3Parser.java:742)
    at org.asdt.core.internal.antlr.AS3Parser.as3CompilationUnit(AS3Parser.java:635)
    at org.asdt.core.internal.antlr.AS3Parser.compilationUnit(AS3Parser.java:369)
    at uk.co.badgersinfoil.metaas.impl.ASTActionScriptParser.parse(ASTActionScriptParser.java:35)
    ... 42 more
    [LOG] Unexpected problem on thread AWT-EventQueue-0: Unexpected token LT at line 50

    The simple workaround is to comment out those lines of code just while refreshing attributes.

    8
    Resolved Questions / Hazard when using copy of game folder
    « on: May 21, 2012, 01:21:23 am »
    Hi.

    I just had an unfortunate experience with working with a copy of a game folder. I.e. rather than using save as, I had apparently ( a few days ago, just copied the game folder into a new one called 'Copy of ...' ). Thus of course game.xml wasn't updated.

    I then went back to working on the original game in the original game folder ..

    Today I opened the 'copy of'-game and used save game. The result was that the original game folder was overwritten, overwriting code, scene info, xml, etc., etc.

    I didnt lose that much, because it was a test game for a custom background. It might take me an hour. But I think I should warn about this anyway.

    Perhaps a resolution to this might be test the location of game.xml against the game name when the game is opened. Either refuse to open a game folder where the game name differs from the folder name, or change the game name, so the referencing will work.


    Pages: 1