How can I avoid garbage collection delays in Java games? (Best Practices)
- by Brian
I'm performance tuning interactive games in Java for the Android platform. Once in a while there is a hiccup in drawing and interaction for garbage collection. Usually it's less than one tenth of a second, but sometimes it can be as large as 200ms on very slow devices.
I am using the ddms profiler (part of the Android SDK) to search out where my memory allocations come from and excise them from my inner drawing and logic loops.
The worst offender had been short loops done like,
for(GameObject gob : interactiveObjects)
gob.onDraw(canvas);
where every single time the loop was executed there was an iterator allocated. I'm using arrays (ArrayList) for my objects now. If I ever want trees or hashes in an inner loop I know that I need to be careful or even reimplement them instead of using the Java Collections framework since I can't afford the extra garbage collection. That may come up when I'm looking at priority queues.
I also have trouble where I want to display scores and progress using Canvas.drawText. This is bad,
canvas.drawText("Your score is: " + Score.points, x, y, paint);
because Strings, char arrays and StringBuffers will be allocated all over to make it work. If you have a few text display items and run the frame 60 times a second that begins to add up and will increase your garbage collection hiccups. I think the best choice here is to keep char[] arrays and decode your int or double manually into it and concatenate strings onto the beginning and end. I'd like to hear if there's something cleaner.
I know there must be others out there dealing with this. How do you handle it and what are the pitfalls and best practices you've discovered to run interactively on Java or Android? These gc issues are enough to make me miss manual memory management, but not very much.