Profiling Graphics on the Mac
Saturday, August 20, 2005
I’ve always hated to profile applications. Most general use Java profilers are agony to run. Before anyone tells me to try the NetBeans profiler I humbly ask for a Mac OS X binary of it — that seems to be missing. Apple’s Shark works OK, when it doesn’t crash the app on startup or exit. But Shark and even OptimizeIt slow the application to a crawl. I can count on one hand the number of times a profiler has told me something I didn’t already know. Most of those times, I was profiling someone else’s code. Profiling Axiom #1: Profiling is most rewarding in a team setting or on “inherited” code. By “inherited” I’m referring to code that get dumped in your lap, not some OO concept.
My current profiling target was a game I’d written. After wasting a few hours looking for a Java profiler with good Mac support that fit my budget (Cheap or Free). I decided to return to Shark (part of CHUD). Another half-an-hour wasted trying to start the app with shark, then realizing I had not updated CHUD since installing JSE5. Another 10 minutes to Re-download and reinstall CHUD. The app still bombs with launched thru Shark, but I can launch the app then attach to the process. I did all this plus an hour worth of data-mining to find out what I already knew about my game — It spends most of it time Bliting images, drawing text, and yielding the control of the thread. You see, I’m the only one who has worked on this code which reinforces axiom #1. Profiling axiom #2: Unless you are a beginner, in-depth knowledge of your code will beat profiling. This is one more reason why it is important to understand what your team-mates are doing in a team environment.
However, there are cases when profiling your own code can be useful. Profiling axiom #3: You should profile to double-check any assumptions. The way I found one very bad assumption (for a game anyway) by using something that isn’t a traditional profiler. I was poking the Apple developer tools after being disappointed by Shark and trying various things. A lot of the Apple Developer Tools have names that are in-jokes (maybe?) so I either have to read about them or try them to figure out what they are. However the most useful one I’ve found has a rather straight-foreward name, “Quartz Debug”.

Quartz is the Apple graphics framework and Quartz Debug has some interesting features. Above is the main window of Quartz Debug. The “Flash Identical Updates” options was very useful to me. It will flash red areas of the screen that were updated but exactly the same as the original image. In my game, I use BufferStategy to update the screen and somewhere I had picked up the assumption that this needed to draw the entire screen for every frame (even for identical frames). This meant my game was using 50% of the CPU when, on average, it needs less than 5%. Shark told me I was spending most of my time bliting, Quartz Debug helped learn why I was doing that. When I look back, I feel stupid for having made the assumption in the first place. There is one odd thing, whenever a Java window repaints the grow box in the corner also repaints regardless of if it was needed.

One thing I always wanted while developing games was a simple easy way to tell how many frames-per-second I’m really pushing out. Quartz Debug offers the Frame Meter (see screenshot above) to do that and show CPU usage. The frame meter works for the entire desktop, so if you have a misbehaving program on screen it will skew the results. Quartz Debug also has some other goodies like a window list with lots of information, it lets you enable/disenable Quartz Extreme and Quartz 2D Extreme. One would think a 2D Java game would benefit from Quartz 2D Extreme (which is default off on my machine) but it actually seems to hurt performance.
In summary, know your code and test your assumptions. It is never too early to code for good and efficient performance. While it is true the new performance tweaks would not make the game look any faster on a fast machine they will help it to run on old machines. And please, somebody make an open source Java profiler with decent front-end that actually works on all Java platforms. I know the nature of profiling makes that difficult.