Measuring Frame Rate

BobTest provides a perfect example to start with some optimizations. Before we can do that, though, we need a way to assess performance. Manual visual inspection ("doh, it looks like it stutters a little") is not precise enough. A better way to measure how fast our program performs is to count the number of frames we render per second. If you remember Chapter 3, we talked about something called the vertical synchronization, or vsync for short. This is enabled on all Android devices that are on the market so far, and limits the maximum frames per second (FPS) we can achieve to 60. We know our code is good enough when we run at that frame rate.

NOTE: While 60 FPS would be nice to have, in reality it is pretty hard to achieve such performance. Devices like the Nexus One and the Droid have a lot of pixels to fill, even if we're just clearing the screen. We'll be happy if our game renders the world at more than 30 FPS in general. More frames don't hurt, though.

Let's write a little helper class that counts the FPS and outputs that value periodically. Listing 7-14 shows the code of a class called FPSCounter.

Listing 7-14. FPSCounter.java; Counting Frames and Logging Them to LogCat Each Second package com.badlogic.androidgames.framework.gl;

import android.util.Log;

public class FPSCounter {

long startTime = System.nanoTime(); int frames = 0;

public void logFrame() { frames++;

if(System.nanoTime() - startTime >= 1000000000) { Log.¿("FPSCounter", "fps: " + frames);

startTime = System.nanoTime();

We can put an instance of this class in our BobScreen class and call the logFrame() method once in the BobScreen.present() method. I just did this, and here is the output for a Hero (running Android 1.5), a Droid (running Android 2.2), and a Nexus One (running Android 2.2.1).

Hero:

12-10 03:27:05.230: 12-10 03:27:06.250: 12-10 03:27:06.820: 132ms

Droid:

12-10 03:29:44.825: 12-10 03:29:45.864: 12-10 03:29:46.879: 12-10 03:29:47.879: 12-10 03:29:48.887:

Nexus One: 12-10 03:28:05.923: 12-10 03:28:06.933: 12-10 03:28:07.943: 12-10 03:28:08.963: 12-10 03:28:09.973: 12-10 03:28:11.003: 12-10 03:28:12.013:

DEBUG/FPSCounter(17883): fps: 22 DEBUG/FPSCounter(17883): fps: 22

DEBUG/dalvikvm(17883): GC freed 21818 objects / 524280 bytes in

DEBUG/FPSCounter(17883): fps: 20 DEBUG/FPSCounter(17883): fps: 23

DEBUG/FPSCounter(8725) DEBUG/FPSCounter(8725) DEBUG/FPSCounter(8725) DEBUG/FPSCounter(8725) DEBUG/FPSCounter(8725)

DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930)

fps: 39

fps: 38

fps: 38

fps: 39

fps: 40

fps: 39

fps: 38

fps: 38

fps: 39

fps: 40

DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930) DEBUG/FPSCounter(930)

fps

43

fps

43

fps

44

fps

44

fps

44

fps

43

fps

44

Upon first inspection we can see the following:

■ The Hero is twice as slow as the Droid and the Nexus One.

■ The Nexus One is slightly faster than the Droid.

■ We generate garbage on the Hero in our process (17883).

Now, the last item on that list is somewhat puzzling. We run the same code on all three devices. And upon further inspection, we do not allocate any temporary objects in either the present() or update() method. So what's happening on the Hero?

0 0

Post a comment