Reputation:
I'm currently working on an Android game and ran into a problem regarding communication between Activity and Renderer.
I have an Activity
with a GLSurfaceView
as the content view and a Renderer
that is attached to GLSurfaceView
. The Renderer
contains the game loop. It draws the scene and updates the game state. This seems to be best practice and works smooth so far. The Activity
additionally displays UI elements like buttons or the game score.
The Activity
runs in the UI thread and Renderer
has its own thread. So basically I have to deal with inter-thread communication. I use GLSurfaceView.queueEvent(Runnable)
to call something in the Renderer
thread from the Activity
(e.g. starting the game loop). To call something in UI thread (e.g. updating game score UI element) from the Renderer
I use Activity.runOnUiThread(Runnable)
.
Every time I want to communicate with the other thread a Runnable
must be instantiated. At some point this will trigger Garbage Collection because the VM needs to free memory. This of course will interrupt the game.
Are there any alternatives without instantiating new objects? The goal is to keep the memory allocation constant while the game is running.
Upvotes: 2
Views: 398
Reputation: 6393
I wouldn't mix Android UI elements with the GLSurfaceView. Why, you might ask. Well, the normal UI elements use OGL as a best-effort. If there are certain things that cannot be rendered using OGL, they will be rendered otherwise (software render for example). Also, rendering those elements are subject to the lifecycle of the Activity render loop, thus effectively throttling your game's performance.
There are certain things you can do if you want to minimize the GC runs / queueEvent
calls.
In C++ you allocate your own things and free them whenever you want. The native code is usually used for game physics and stuff like that but you can put OpenGL into it, too.
Like I said, I wouldn't use the normal UI elements but render my own ones using textures (sprites) in OGL, thus eliminating the need for runOnUiThread
.
As for the queueEvent
, that's only needed if your invoked code modifies the OGL state machine (so basically all the gl*
calls). My guess is that you mainly use this event queuing for passing touch coordinates and other "modifiers" to your game logic. In order to get rid of this, instead of modifying OGL directly from the invoked method, change only your model attributes and draw / set the new OGL state in the next render loop (make sure you make changes in a synchronized way, otherwise it can mess up things).
If your game is not graphics heavy and does not need special rendering options, you can use a canvas of a custom View
which will allow you to render texts as well. Note that canvas might use OGL in the end for a lots of things, so for creating casual 2D games, it's still good.
Calling queueEvent
with new Runnable
instances is not necessarily a bad thing. The GLThread, that runs the Runnable instance, nullifies it (sets it to null
) after taking it from the queue and running, which tells the GC that it can free its memory anytime. This is an optimization technique used widely in Java programming because the GC will not have to test certain things about this object anymore. Thus, the GC runs will not take as much time as you think.
Upvotes: 1
Reputation: 52313
Don't allocate Runnables for every message. Create a Handler for the thread receiving the messages, and get your Message objects with e.g. obtainMessage()
to avoid allocations.
You can find multiple examples of this in Grafika, which takes steps to minimize or eliminate allocations across the various activities. Android Breakout has no[*] allocations during gameplay (though it doesn't use any View UI while playing).
Recommendations to switch to native code are generally overkill, especially if your only intent is to avoid garbage collection.
The best tool for evaluating the state of your game is the DDMS allocation tracker, which shows the N most recent allocations.
[*] I haven't checked Android Breakout in a while. The goal was zero allocations.
Upvotes: 2