However, the simulation would slow down considerably after adding a few dozen balls. This was largely due to the quadratic nature of my naive collision detection. In order to remedy the speed problems I implemented[2] a quadtree I found online to assist me in culling a lot of my expensive collision checks. The bounds of the quadtree sections will appear as you begin to add balls.
Unfortunately the quadtree wasn't the performance savior I expected it to be. I didn't notice a dramatic improvement in the number of balls I could support. I also introduced a bug with the quadtree version where certain collisions are missed entirely.
Perhaps I should revisit this simulation and see where I was off.