Better Off Android – 1.1 Bit:Update

Android-logo

Last year I put together four simple Android games – Bit:Shift, Bit:Run, Bit:Rise & Bit:Fall.

I wrote these game using scratch code – That is code ‘scratched‘ together from any samples, tutorials, etc I could find on the internet – along with a little guesswork on my part to fill in the gaps..

It creates very messy code, which I wouldn’t want to show anyone. But is a surprisingly useful technique for learning quickly & having a product to use at the end of it all.

By and large I’m pretty happy with these games, there’s not much to them, but I think they are fun to play & have all the elements I wanted to try out – online highscores, achievements, ability to purchase & what I hope is an entertaining diversion at its core.

However they are not without their problems – The most obvious of which is scrolling.

Currently scrolling on these games is atrocious – For the most part – with Bit:Rise & Bit:Fall especially it’s not an issue – But with Bit:Run and especially with Bit:Shift it’s very noticable & takes away most of the fun from playing the game.

I need to try and fix this – If I can’t remove the problem entirely then I need to at least try to minimise their impact.

 


 

Since a scroll fix would involve updating all the games code; I figured I’d do a little housecleaning at the same time.

Really I need to tidy the code & do a little restructuring (not that much) – But I’ll save that for the next update. This time I thought I’d do some optimisation – Especially trying to get the garbage collector to run as infrequently as possible.

 


 

I have four games (Bit:Run, Bit:Rise, Bit:Fall & Bit:Shift) – each games has two versions (One version for GooglePlay , the other for the Amazon App Store).
I used Google’s ‘Performance Tips‘ as a primary guide – alongside a few google searches to decide which to focus on.

Settling on six processes;

1. Remove getters & setters
2. Use direct reference with For loop conditions
3. Convert floats to ints
4. convert int to shorts & bytes
5. Change variables to static & static final
6. Object pools

 

Links:
Performance Tips
Coding for performance and avoiding garbage collection in Android

 


 

1. Remove getters & setters

I’ve always been taught to use getters and setter & I’ve been pretty consistent in using them in code. But never been a huge fan – Unless the getters and setters actually do something (filter the values being retrieved or updated) – They didn’t seem to do anything other than provide an extra layer (& extra code) for what was essentially direct access to an objects variables.

For Android – within an class anyway – Google agree; ‘on Android. Virtual method calls are expensive, much more so than instance field lookups. It’s reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

 


 

2. Use direct reference with For loop conditions

The title isn’t particularly clear; so I’ll try to explain through example;

I had a lot of for loops that looked like this;

for(int counter = 0; counter<array.length; counter++)

The problem here is ‘counter<array.length‘ – Because JIT will need to reconfirm the array.length every loop it’s unable to optimise performance.

A better solution (one which I have currently implemented) is to assign ‘array.length‘ to an integer before looping;

int arrayLength = array.length;
for(int counter = 0; counter<arrayLength; counter++)

JIT now has a static value to check against; it can optimise the loop’s performance.

However, an even better method (& one which I haven’t yet implemented) would be to use Java’s ‘enhanced for loop syntax’

for (Foo a : array) {

 


 

3. Convert floats to doubles

Google explainss;

As a rule of thumb, floating-point is about 2x slower than integer on Android-powered devices.

In speed terms, there’s no difference between float and double on the more modern hardware. Space-wise, double is 2x larger. As with desktop machines, assuming space isn’t an issue, you should prefer double to float.

Searching around, the vast majority of people seemed to agreed – With the consensus – use doubles by default & floats only when absolutely necessary.

When are floats necessary? – My games had three, rather major areas, where using floats was necessary;

  1. When creating a large number of objects (e.g. particles for explosions) – Explosions create a lot of particles – I don’t need absolute accuracy when drawing them & using floats means they take up far less space in memory.
  2. Matrices- I use basic graphics for the Bit: games – using matrices to manage them. In java Matrix methods have floats as parameters rather than doubles.
  3. Graphics – Beyond the matrix, most of the graphics methods in Java use floats rather than doubles – GPU’s are generally optimised for float processing – some can’t handle doubles at all.

While doubles are preferred, they are not always feasible – especially with game development.

I guess as a rule – If it’s CPU work, use a double, if its a graphics operation, use floats.

 


 

4. convert int to shorts & bytes

I figured, since I’m use doubles, which take up twice the space of floats – I’d try to save some space by replacing integers (32-bit  min value:-231  max value:231-1) for short’s (16-bit min value:-32,768 max value: 32,767) or bytes (8-bit min value:-128 max value: +127).

This would be especially useful in for loops – Most of my four loops count to less than 10 – a byte which has a value between -128 – +127 should do the job nicely.

As it turns out this is bad idea;
Java is optimised for processing integers, but not shorts or bytes.

Byes & shorts will probably be promoted to integers – a process which will take up processing time to perform & will mean no space has been saved

The Java Virtual Machine models stacks and object fields using offsets that are (in effect) multiples of a 32 bit primitive cell size. So when you declare a local variable or object field as (say) a byte, the variable / field will be stored in a 32 bit cell, just like an int.

Which isn’t to suggest that shorts & bytes aren’t useful – Just not for purposes I had in mind.

Links:
In java, is it more efficient to use byte or short instead of int and float instead of double?
Why does the Java API use int instead of short or byte?

 


 

5. Change variables to static & static final

This makes sense when trying to avoid calling garbage collection. The garbage collector is called when enough elements are orphaned or disconnected (e.g. setting an instantiated object to null). Since static objects exist throughout the lifetime of the application there’s not disconnection.

So, although it ensures a larger constant memory footprint, with fewer objects being destroyed/recreated – There are fewer reasons for Java to run garbage collection.

On a method level, Google explains;
If you don’t need to access an object’s fields, make your method static. Invocations will be about 15%-20% faster. It’s also good practice, because you can tell from the method signature that calling the method can’t alter the object’s state.

Optimisation is further increased if you can declare the objects static final since ‘the constants go into static field initializers in the dex file. Code that refers to intVal will use the integer value 42 directly, and accesses to strVal will use a relatively inexpensive “string constant” instruction instead of a field lookup.

Though, for for static final, it’s worth noting the caveat; ‘This optimization applies only to primitive types and String constants, not arbitrary reference types. Still, it’s good practice to declare constants static final whenever possible.

 


 

6. Object pools

Another garbage collection management method. Object pools use the same principle as using static variables.

Wikipedia explains; ‘initialized objects [are] kept ready to use – [in] a “pool” – rather than allocating and destroying them on demand. A client of the pool will request an object from the pool and perform operations on the returned object. When the client has finished, it returns the object to the pool rather than destroying it; this can be done manually or automatically.

So, for example – You have a game in which X number of bad guys are going to be active at any one time. Which you can’t guarantee how many will be active, you know it will never be more than 32 at any one time.

To manage the bad guys – You may create a List – of type BadGuy – This way you can easily add new BadGuy’s when they are needed – & remove old BadGuy’s once they have been dispatched by the player. It also means you’re not using up any more memory at any one time than you absolutely need to.

This is fine, except, after x number of BadGuy’s have been removed from the list, the garbage collector will run which will take up precious processing time.

To alleviate this, instead of a list – you use an array – of type badGuy – since we know there’s never more than 32 active bad guys we make the array 32 elements in size.

Also adding a boolean to the badGuy object – called, say isActive – This allows the program to determine if the BadGuy is alive (and should be updated/drawn to screen) or dead (& ignored)

Now when a BadGuy is killed, instead of removing them from the list, you set isActive to false.

When looping through the array (for update or drawing) – you check ‘if badGuy[counter].isActive‘ – to ensure out of play bad guys are not processed.

When adding a new bad guys into the game game; you find a cell in the array with a bad guy whose ‘isActive == false‘ – re-Initialise & they are back in play. You can find an empty cell by looping through the array and checking each element, but a better option is to keep an index of available cells

Like static objects, this has the downside of having a consistently larger memory footprint – but lowers garbage collection calls dramatically.

While I don’t have that many elements active at any one time, objects are constantly falling off the bottom of the screen and being added to the top.

Since this happens in a very controlled manner, converting from lists to basic object pools was pretty straight forward.

Links:
Simple object pool

 


 

Thats was about it – There always more I can do; & for these games, there’s a LOT more that needs to be done – but for now, I figure that’s enough procrastination – I need to get to the heart of the problem & actually fix the scroll issue.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s