Casting vs Not Casting in Strict Mode and not in Strict Mode
September 18th, 2010
Preamble
Actionscript is, for the most part, a dynamically typed language, which means that the types (i.e. String, int, GameObject) of variables are checked at run-time rather than at compile-time like they are in C and Java. This is supposedly beneficial to the programmer since such a language is more flexible. All sorts of crap like this is valid:
var i = new GameObject(); i = "1";As you can see it’s possible to change the type of a reference to something entirely different. This can generate type errors at run-time since later you may try to call i.update(). Although this example is very obvious real world examples can be more nuanced and thus more complicated to find and fix. Casting and using ‘Strict Mode’ is a technique to essentially make Actionscript a little bit like a statically typed language. The performance boost comes from firstly doing as much as possible at compile-time (thus less at run-time) and secondly helping the process of type checking by casting. Read more: Code, Results and Conclusion
On Android, and in general, you want your application or game to be responsive. So operations that take a long time to finish or block I/O should not be preformed on the UI thread otherwise the UI becomes clunky and unresponsive. To solve this problem any CPU intensive or I/O blocking operation are preformed in a separate thread. Unfortunately this creates another problem, which is how do we update and control the UI from this separate worker thread.
This is where Handlers come into play they allow you to send Messages (information and instructions) from the worker thread to the UI thread. A Message can contain ints using the fields arg1 and arg2 and an arbitrary Object using the obj or a Bundle using the setData(Bundle data) method.
So here’s an example of how to use Handlers:
public class DataView extends View {
final static int FAILURE = 123, DATA = 124;
DataHandler handler;
ArrayList data;
boolean failure = false;
public DataView(Context context, AttributeSet attrs) {
super(context, attrs);
handler = new DataHandler();
(new Thread(new WorkerRunnable(this))).start();
}
@Override
protected void onDraw(Canvas canvas) {
// draw something based on data…
}
private class DataHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case FAILURE:
failure = true;
invalidate();
break;
case DATA:
data = (ArrayList) msg.obj;
invalidate();
break;
default:
super.handleMessage(msg);
break;
}
}
}
@Override
public Handler getHandler() {
return handler;
}
}
public class WorkerRunnable implements Runnable {
private DataView dataView;
private ArrayList dataObjects = new ArrayList(10);
public WorkerRunnable(DataView dataView) {
this.dataView = dataView;
}
@Override
public void run() {
boolean success = true;
// some io or cpu heavy operations
Message msg = Message.obtain();
if(success){
msg.what = DataView.DATA;
msg.obj = dataObjects;
}else{
msg.what = DataView.FAILURE;
}
dataView.getHandler().sendMessage(msg);
}
}
Explanation
The DataView spawns a Thread that runs a WorkRunnables code, which performs some IO or CPU heavy operations. The WorkRunnable informs the UI once it has finished (or failed) by sending messages to the custom written Handler.
Flash / ActionScript 3 Performance: Traditional Main Loop vs Multiple Event Listeners
January 11th, 2010
Main Loop
Traditionally games (action and time-dependent games in particular) are written as a loop that runs as fast as possible continuously updating the graphics, physics, AI and such. This is because in C that is how applications with a GUI were written, a loop which updates the UI and then sleeps for a while.
Multiple Event Listeners
This method is specific to ActionScript and it’s fancy listeners. Rather than having a main loop that updates all of the objects, the objects have event listeners attached to themselves. Listeners are used a lot in ActionScript this is mainly because there isn’t blocking like in Java. For example in Java reading a line from a network Socket would block until the socket had something to read (or timed out), but in ActionScript you have to add a Listener that is triggered when the Socket has something to read.
In the case of the ENTER_FRAME event however all of the multiple Listeners are responding to the same event and are therefore adding to the amount of computation required.
Code
The code for this test is split into two parts, one of the documents classes uses a main loop and the other uses a class called ParticleSpecial which handles it’s own ENTER_FRAME events.
Main Loop Document Class:
Conclusion
Although using multiple event listeners can make your code neater and more organized, the technique is far too slow in performance critical fast paced games.
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.getTimer;
public class MainLoop extends MovieClip {
private var fps:FPS=new FPS();
private var particles:Array=new Array(1000);
public function MainLoop() {
for (var i:uint = 0; i<particles.length; i++) {
particles[i] = new Particle();
addChild(particles[i]);
}
addEventListener(Event.ENTER_FRAME, update);
}
private function update(e:Event) {
for (var i:uint = 0; i<particles.length; i++) {
particles[i].x=275+100*Math.cos(getTimer()*0.001);
particles[i].y=200+100*Math.sin(getTimer()*0.001);
}
}
}
}
Multiple Event Listeners Document Class:
package {
import flash.display.MovieClip;
public class Listeners extends MovieClip {
private var fps:FPS=new FPS();
private var particles:Array=new Array(1000);
public function Listeners() {
for (var i:uint = 0; i<particles.length; i++) {
particles[i] = new ParticleSpecial();
addChild(particles[i]);
}
}
}
}
ParticleSpecial Class used by Multiple Event Listeners Document Class:
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.getTimer;
public class ParticleSpecial extends MovieClip {
public function ParticleSpecial() {
addEventListener(Event.ENTER_FRAME, update);
}
private function update(e:Event) {
x=275+100*Math.cos(getTimer()*0.001);
y=200+100*Math.sin(getTimer()*0.001);
}
}
}
Results:
| Test | MainLoop (fps) | Listeners (fps) |
| 1 | 59.9 | 29.8 |
| 2 | 59.9 | 29.7 |
| 3 | 60.0 | 30.5 |
| 4 | 59.8 | 29.3 |
| 5 | 60.0 | 30.7 |
| 6 | 59.8 | 29.0 |
| 7 | 59.9 | 30.8 |
| 8 | 59.9 | 29.2 |
| 9 | 60.0 | 30.6 |
| 10 | 59.3 | 29.3 |
| Average | 59.8 | 29.9 |
Flash / ActionScript 3 Performance: Object Recycling
January 6th, 2010
Preamble
ActionScript 3 despite the hype of the AVM2 still can be very slow, particularly when writing games because games often push your hardware ways that other applications simply will not. A form or image gallery for example will for a lot of the time be doing nothing waiting for the user to interact e.g. click a button. A game on the other hand will constantly be drawing, calculating physics, responding to collisions for a number of objects and then there’s AI on top of those.
Although this series is most relevant to games the findings can be applied to most programming projects especially in languages such as Java and ActionScript. After all performance and efficiency is important predominantly when memory or processing power is limited i.e. on handheld devices.
Object Recycling
Object recycling is reusing memory that has already been allocation by modifying variables rather that allocating more memory using the new statement. Modifying the variables such that the object is effectively a new object but in the same memory. Here’s an explanatory example:
var lc:LovelyCharacter = new LovelyCharacter("David", "17-02-1902", 10, 0.5);
// not recycling and bad
lc = new LovelyCharacter("Terry", "03-05-2004", 14, 0.1);
// recycling and good
lc.name = "Terry";
lc.dob = "03-05-2004";
lc.numOfChildren = 14;
lc.interest = 0.1;
// or for convenience define a reset function
lc.reset("Terry", "03-05-2004", 14, 0.1);
As you can see the instance lc is the same after either process however the recycling process didn’t allocate more memory. Allocating more memory also means that the old memory is released which results in the garbage collector (gc) having to do some work ultimately slowing down the game since this process takes time.
Read more: Code, Results and Conclusion