biais.org

Sunday 16 May 2010

Profile your OpenGL ES iPhone applications

Introduction

This article explain how to trace OpenGL ES function calls of your iPhone application but you can trace any other kind of function call using this technique. Note that I'm not sure it's the best way to do that but I didn't found any other tool able to trace all function calls (Instruments can sample process usage, but I didn't manage to trace all function calls with it).

The technique is based on a base gdb script:

  1. break on glSomething functions,

  2. for each break, use commands to print the frame #1 (where the glSomething has been called in your source code).

Sample translation for the glEnableClientState function:

set breakpoint pending on # Enable breakpoints on symbols not yet loaded

break glEnableClientState
commands      # start command when the break is 
silent
frame 1       # print the frame #1
continue      # continue to the next break
end           # end the command list

Following scripts and iphonesim source code is available on my iphone-opengl-profiler github project page

Note: if you want to execute the following guide, you should download the projet and compile the iphonesim binary.

Example use

Generate gdb script

I wrote a small script to generate the list of glFunctions you use in your program, for example for the OpenGLES sample project:

$ gdbscripts/listGlFunctions.sh "/Users/max/work/iphone apps/OpenGLES/build/Debug-iphonesimulator/OpenGLES.app/OpenGLES" \
  > glFunctions.txt

Then run the following script to generate the gdb script from your function list:

$ gdbscripts/generate-gdb-trace.sh glFunctions.txt > gdbscript.txt

Now you're ready to launch your application and attach gdb.

Run your iphone app in the simulator

Run the iphonesim binary that will launch your application in the simulator, run gdb and attach it to your process.

$ iphonesim launch "/Users/max/work/iphone apps/OpenGLES/build/Debug-iphonesimulator/OpenGLES.app/OpenGLES" \
  -debug YES -sdkVersion "3.0" -gdbcommands gdbscripts.txt > gdb-trace.log

Ctrl-C when you decide to stop your applicaton (when you think you gathered all profiling data you need).

Analyze gathered data

I wrote a last script to filter glSomething commands, you can run it:

$ cat gdb-trace.log | gdbscripts/opengl-state-tracer.sh | head
glGenFramebuffersOES(1, &ViewFramebuffer);
glGenRenderbuffersOES(1, &ViewRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, ViewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
glGenRenderbuffersOES(1, &ViewDepthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, ViewDepthRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, ViewFramebuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, ViewRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, ViewDepthRenderbuffer);

Get basic statistics:

$ cat gdb-trace.log | gdbscripts/opengl-state-tracer.sh | sort | uniq -c | sort -n -r
461 glMatrixMode(GL_TEXTURE);
461 glLoadIdentity();
249 glMatrixMode(GL_MODELVIEW);
198 glMatrixMode(GL_PROJECTION);
...

Have fun profiling you're OpenGL ES iPhone applications !

Friday 20 November 2009

Brute crawling the App Store.

I was looking for statistics about iPhone applications and raw data to extract my own statistical data. After a quick googling, I didn't found any way to crawl the App Store easily, so I tried to do it quickly.

Each application data is accessible via HTTP on this url: http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=FIXME-ID where FIXME-ID is a number indetifying an application. To make an HTTP request on this url, you have to fake the User-Agent (iTunes/9.0.2 (Macintosh; Intel Mac OS X 10.5.8) AppleWebKit/531.21.8 works).

With theses informations you can write this kind of shell script to brute crawl the App Store:

OUT=downloaded
ENDID=337489918
CURDIR=0
WGETMAX=40
mkdir -p $OUT/$CURDIR
cd $OUT/$CURDIR

i=$ENDID
while [ $i -ge 0 ]; do
    if [ $((i % 25)) -eq 0 ]; then
	CURDIR=$(($i / 10000))
	if [ ! -d ../$CURDIR ]; then
	    mkdir  ../$CURDIR
	fi
	cd ../$CURDIR
	# Limit the maximum number of wget process
	nwget=$(ps auxxwww|grep "wget"|grep apple|grep -v grep|wc -l)
	if [ $nwget -ge $WGETMAX ]; then
	    sleep 1
	    continue
	fi
    fi
    i=$(($i-1))
    echo $i
    wget "http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=$i&mt=8" \
            -U "User-Agent: iTunes/9.0.2 (Macintosh; Intel Mac OS X 10.5.8) AppleWebKit/531.21.8"\
            > /dev/null 2> /dev/null && if [ $(\ls -l "viewSoftware?id=$i&mt=8"|tr -s " "|cut -d " " -f 5) -le 5000 ];\
            then rm -f "viewSoftware?id=$i&mt=8"; fi  &
done

Sunday 8 November 2009

Stupnik: my first iPhone game available in the Appstore

My first iPhone game has been accepted in the Appstore. I worked on it during february 2009 and I stopped because of lack of motivation and lack of graphic design talents ;). Recently, I took 2 full days to work on it, I polished some things (sounds and online high scores) and decided to submit it for free. A few days ago, Apple sent me an email telling me that the game was downloadable in the Appstore.

Here is a short video of the game:

Friday 4 September 2009

Orange Slice: iPhone game development

I'm currently working on an iPhone game during a part of my spare time. The project name is OrangeSlice. It's based on the very good 2D graphics library cocos2d-iphone

Here is a video I captured from the iPhone Simulator (that doesn't support accelerometer, so the all the game features are not showed):