Android Performance Help

Monkey Targets Forums/Android/Android Performance Help

BigAnd(Posted 2013) [#1]
Hey guys. Just looking for a bit of advice really.

I am having a bit of a performance issue on my Galaxy S4. My game runs without problem on iPhone(4,4s), iPad(Rev3), PC(rubbish laptop and main PC) and Mac(old Mac Mini) but it drops to a crawl on my Droid.

Its a full screen scrolling platformer so it can be drawing nearly 2000 objects each frame. Thats, say, a maximum of 60x33 32 pixel square tiles.

Like I said, on the other platforms I am getting 60fps but on the Droid its about 17fps.

My draw routine follows:



And quick dev video of what it does here:


Should I be using arrays?
I found them to be faster than lists.

Should I be using DrawImageRect or something else on Android?

Just looking for what other people do really.

Cheers,
Andy.


eme64(Posted 2013) [#2]
Hi Andy

I had some problems recently with speed on Android too.
My way to find out was to count the amount of Milliseconds my OnUpdate() and OnRender() needed. The result is, that HTML5 is stronger in Calculating and Android is far stronger in Drawing.
Therefore I suspect it is your calculating that makes trouble.

Question: how are you shifting the DRAWlist's content? If you are shifting each Square individually you should consider having an offset variable for X and Y and apply them only directly in the drawing-command.

I hope this is of help to you
Cheers,
eme64

Edit: Some more code could help us helping you ;)


BigAnd(Posted 2013) [#3]
Cheers for your input eme64.

I have already got in place the timing of the logic and of the render which is why I was concentrating on speeding up the render as it was showing big slowdowns.

The squares/tiles are not being moved individually. Its just a big array for the map and it only ever draws what can be seen. And yes, its just one offset for everything. Its as simple as I can do it really.

At the moment there isn't much going on in game at all so no logic bottlenecks.

Again, thanks for input and I will do some more investigations.

LibGDX uses some sort of cache for sprites that dont change, so will give that a look over how its implemented but it may be more of a low level thing.


AdamRedwoods(Posted 2013) [#4]
make sure to use sprite atlases for Android. for me, this was essential. i see you're already doing this.

there is also an undocumented command, which may help batch your sprites:
Function DrawPoly( verts#[],image:Image,frame:Int=0 )


you may need to use Android Monitor to profile the code.


BigAnd(Posted 2013) [#5]
Nice one Adam. Will gave this a go tonight.


silentshark(Posted 2013) [#6]
60x33 32 pixel squares?

You are coding at a high resolution -1920x1056 is it?

Maybe you could try recoding to run a lower res, which would undoubtably speed things up. There was a threat a while back about what resolutions follk here were coding in, and the general picture was a lot lower than what i think you are aiming for..

Anyway, appreciate this is stating the obvious, but i hope it provides fod for thought.


BigAnd(Posted 2013) [#7]
Thanks for the input silentshark.

I have tried it at 512x384 and its not much better.

I got a slight performance increase by adding:
<screen android:screenDensity="480" android:screenSize="normal" />

to my manifest. Obviously, only relevant to the S4.

I am still looking at the drawpoly option and building big polygons out of my map tiles. Its working ok but I am not sure I am a good enough coder to get the results I need. Although by typing this reply, I have had a thought about how I can go about this better! Strange how your thought processes work :)

Cheers.
Andy


MikeHart(Posted 2013) [#8]
Are you always drawing all tiles, even when they are not visible? If yes, avoid this.


BigAnd(Posted 2013) [#9]
Yes Mike, I am drawing as little as possible. Just a screens worth plus an extra row and column for the scroll.

I am getting some good initial results with the DrawPoly but need some extra time on it, which will hopefully be this weekend. Will post results good or bad.

Cheers,
Andy.


MikeHart(Posted 2013) [#10]
Another thing I would try to avoid is to set blend, alpha and color everytime instead only when it changed compared to the former tile you have drawn. You also set the handle all the time, where I wonder why.


BigAnd(Posted 2013) [#11]
It only sets the handle on the 'sprite' type every time but does it only once or when the type changes on the 'tile' type in the code above. Same with all blending, colour, scale and alpha.

Like you suggest, I found it slowed the process down greatly.


Salmakis(Posted 2013) [#12]
well, i dont have any problems with performance in such things on android.
I just tried out my tilemap on my android phone:

https://dl.dropboxusercontent.com/u/23933614/tilemap/MonkeyGame.html

i got an Xperia U, wich is not the HighEnd class of androids at all.
i got some laggyness if i zoomed out most as possible, but all valuable zoom levels are no problem.

My drawing code looks like this:
(cropped out some stuff wich is not related here (entitys, effects, etc)




I got the tileframes wich will be used in a arrayofarrays(map.tileframes[][])
the most importand thing is to not draw all of them.
so i got a loop wich trys to only covering the visibile (well it draws some more but its not alot so it is okay)

and as some said, you should try to dodge the SetColor and such stuff if its possible, it seems like this slows things down alot.

if you want an APK to test if it is maybe not a problem of your code, but a problem with your device and monkey at all:

https://dl.dropboxusercontent.com/u/23933614/tilemap.apk
(runs fine on my device!)

(the apk is found as "Fruit Dropper" in the menus (i just adjusted the templates for my last project))


BigAnd(Posted 2013) [#13]
Thanks for that Salmakis and it works great on my device. So it is me thats being dumb! :)

I hear what you are saying about just drawing what I need to and I am doing just that. I am going to check my iteration that I am doing through the sprites and break it down a bit more. I am also going to split up my tile and sprite drawing.

Again, thanks for the great input.
Andy.


BigAnd(Posted 2013) [#14]
Just like to say a big thanks to Salmakis as his bit of code got me right back where I needed to be.

I basically switched back to DrawImage from DrawImageRect and also drawing my tiles separately from my sprites.

I did have all my sprites and tiles on a single texture for speed but now I only have 1 or 2 texture swaps depending on the layers in my map. e.g.
Draw Background Map Layer (SWAP) Draw Sprites (SWAP) Draw Foreground Map Layer.

Also, as eme64 stated above, using DrawImage also cut down a lot of repeated calculations I was doing again and again each frame.

Very happy that I am now back up to 60fps all all my target devices and still runs acceptably on my old iPhone 3GS.

Thanks once again for everyone's input. I may actually now get the game finished.


Salmakis(Posted 2013) [#15]
for this i do have my own variant of image frames, wich i call imagemaps.
you can load 1 texture and assign several atlas maps and stuff on several areas of the image.
also i have a bitmap font system written by myself wich is based on the same system.
so i have font, tiles, gui and sprites on one 2048x2048 texture.

its very easy to use, i would put it into the module lib for all, if someone is interested


computercoder(Posted 2013) [#16]
That sounds pretty nifty Salmakis :) Outside of using atlas maps, I did something similar in BlitzMax. I have yet to produce anything like it in Monkey.


Salmakis(Posted 2013) [#17]
okay computercode, done :)

http://monkeycoder.co.nz/Community/posts.php?topic=6033#69093