Avoid Unnecessary Object Allocations
Moscrif uses Garbage Collector to maintain an allocated object and an object creation is never free. Thus, you should avoid creating object instances you don't need to. If you allocate an object in application loop, you will force a periodic garbage collection and you will decrease the performance in general.
Release Unused Resources
Some objects can hold associated system resources. For example, the opened files hold a handle to the underlying system files. Opened socket or a web request have allocated resource(s) related to a network communication. Using a bitmap consumes huge memory or it can be represented as an OpenGL texture in the system. In these cases, it is very important to release system resources. Release is made by different functions depending on its class:
-
Stream instantiates a file/socket/string buffer object, that must be released using close function
-
WebClient objects must use close function
-
Timer objects have dispose function to be used
-
Sensor objects call dispose function when they are no more required
-
Animator and AnimatorChain have stop function
- etc…
You have to release these system resources yourself as soon as they aren't longer required. Garbage collector can release your unused object automatically, but GC won't never release system resources.
Prefer Singletons
A singleton is a design pattern that restricts the number of class instances to just one. There are many scenarios when exactly one object is needed to handle the logic. Some examples of cases when singleton can be used:
- Instance of main application or game object
- Most of forms, views or scenes. E.g. When you have just one "high score scene", you will implement it as a singleton
- Most of graphics objects like Paints, Shaders, Bitmaps, Fonts etc…
Keep in mind, the latest iPhone or Galaxy have a fraction of your desktop computer's "RAM" memory, though we are talking about hundreds of megabytes. Those hundreds are for all applications and OS, not just for your app or game. Here is an example of lazy initialised singleton:
class Singleton {
// static (class) member
var _instance = null; function this()
{
assert Singleton._instance == null;
Singleton._instance = this;
} //
property instance(v)
{
get {
// this is static!
assert this === Singleton;
if (Singleton._instance == null)
new Singleton();
return Singleton._instance;
}
}
} // access to singleton using "instance" property
var ins = Singleton.instance; console << (ins === Singleton.instance) << "\n";
Avoid Internal Getters and Setters
It's a common practise to use getter to access the class fields. This is an excellent and reasonable idea to follow common object-oriented practices and have getters and setters in the public interfaces. However, within a class you should always access the fields directly. In fact, a getter and a setter are virtual functions, which are more expensive than member field lookup.
If you build geometry framework, a Point class will look like:
class FrameworkPoint { function this(x, y)
{
this._x = x;
this._y = y;
} property x(v) {
get return this._x;
set this._y = v;
} property y(v) {
get return this._y;
set this._y = v;
} function setPos(x, y)
{
this.x = x;
this.y = x;
} function print()
{
console << "[" << this._x << ", " << this._y << "]\n";
} } var p1 = new FrameworkPoint(10, 20); p1.print();
But if you build your game or app, your Point class will look like:
class InternalPoint { function this(x, y)
{
this.x = x;
this.y = y;
} function setPos(x, y)
{
this.x = x;
this.y = x;
} function print()
{
console << "[" << this.x << ", " << this.y << "]\n";
} } var p2 = new InternalPoint(10, 20); p2.print();
Optimize Loops
Very simple trick to reduce the cost of getting the array length is to put it into local variables, avoiding the lookups. Here is the slow way:
var arr = ["a", "b", "c", "d", "e"]; for (var i = 0; i < arr.length; i++) console << arr[i] << "\n";
And here is fastest way:
var arr = ["a", "b", "c", "d", "e"]; var len = arr.length; for (var i = 0; i < len; i++) console << arr[i] << "\n";
If an order doesn't play a role, you can use also:
var arr = ["a", "b", "c", "d", "e"]; for (var i = arr.length - 1; i >= 0; i--) console << arr[i] << "\n";
It is also good practise to use for (… in …) enhanced syntax, that is already internally optimized:
var arr = ["a", "b", "c", "d", "e"]; for (var i in arr) console << i << "\n";
Other
If you are developing a 2D game in Moscrif, you will find this artice describing a game optimalization helpful.
|