The Power of Pahole


I am still working on CoinChaos, after Rae Jam has completed, but I have dived down something of a rabbit hole of optimization and weird game crashes. "Go slow to go faster" is a concept that appears in a lot of endeavours, from programming, to mindfulness, to distance running  even. 

I've definitely been paying the price in the last three weeks of rushing to get as much completed as possible during Rae Jam. My code... was not in the best state in the end ;)

What have I learned?

The Chipmunk2D PostSolve Callback:

The Chipmunk2D cpSpaceAddPostStepCallback is the recommended place to add and remove shapes and bodies from the Chipmunk simulation correctly, and safely. All of the Chipmunk2D example code shows this pretty clearly! 

Unfortunately I missed this tiny detail myself. It meant I was encountering physics simulation oddities due to removing cpShapes and cpBodies from the Chipmunk simulation pretty much whenever I felt like it in the game code.

Fortunately I'm using the State pattern which made it easy to refactor my code so the game Update functions are occurring inside cpSpace post step callbacks, meaning they can happily add and remove shapes to the Chipmunk space. My State_Update calls went from something like this:


To this (where everything Update was previously doing is moved into the GameStateGame_PostStepCallback function):


There's one trick with cpSpaceAddPostStepCallback, in that it's one shot. The callback is called once duringthe cpSpaceStep. The solution to that is simply to register the callback before every cpSpaceStep is called, which you can see happening above.

Pahole:

I'm coding on in C, using GCC on Ubuntu Linux, because I find this OS generally a better experience than Windows these days (which regrettably I'm forced to use in my day job).  Most Linuxes include the excellent pahole tool, which I only discovered recently. You can get it on Ubuntu with: sudo apt install pahole

This is a very handy tool that lets you example the binary layout of the various C structs used by both the playdate SDK and your own code. In particular it shows you padding, and 'holes' that are introduced to your structures for alignment purposes, as well as how expensive your structures are to load into the CPU cache - aka 'cachelines'.

This lets you easily see binary layout of structures (handy when debugging), the size of structures (so you can worry about cache loads) and reduce space wasted by holes and padding (which lets you rearrange struct members for better memory usage). For example my BoardDef struct could use some simple reorganising to remove wasted bytes:


If you're building your playdate games using the stock playdate SDK Makefile and example projects, you'll be compiling to two versions of your final game:

  1. A .so shared library - typically called pdex.so which runs on the local playdate Simulator.
  2. An .elf binary - typically called pdex.elf which is what runs on the actual playdate hardware.

You can run pahole on either of these files, just be aware as they're compiled for different platforms (the .so the CPU of your dev machine, the .elf for the ARM M7 CPU of the playdate device), you'll definitely see differences in structure sizes between the two. 

Just make sure you're running pahole on the file that's relevant to you at the time!

Hopefully another CoinChaos update coming soon!

Get Coin Chaos

Leave a comment

Log in with itch.io to leave a comment.