This project is read-only.

Garbage

Mar 21, 2010 at 6:04 AM

I've seen the same issue crop up a few times on various forums and in at least one Live Indie Game in peer review that is using box2d.xna. The problem is that World.Solve and World.SolveTOI spew garbage like no one's business. The author has rightly stuck warnings there about it, and I've been telling people how to fix it by caching the working lists those functions use. I was wondering why this wasn't already resolved, since the author obviously knows about the problem and there is such an easy fix, and if we could get an 'official' fix.

Mar 21, 2010 at 8:22 AM

It is just something we haven't gotten around to yet.  We intend to comb through the engine for these kinds of garbage optimizations and make them all at once.  If you already have a fix we would welcome the patch.

Our goal is to eventually get down to no garbage per frame.  We want to be careful about how we achieve this because we do not want to stray too far from the original C++ Box2D which is still actively developed (and which we have been continuing to port over to Box2D.XNA).  There are other optimizations we would like to make that also need to be taken into account, such as parallel island solving (using up to 5 of the hardware threads on Xbox 360).

Overall we did a lot of work early on to reduce garbage per frame and got it down significantly from where it would be with a naive port.  In terms of FPS we were seeing diminishing returns as we approached bottlenecks in the actual CPU on XBox 360 and shifted more of our focus to inlining math operations and other non-algorithmic perf optimizations.

Since we made the original port we have been working on a game that actually uses Box2D.XNA and only making changes necessary to support shipping that game (http://www.youtube.com/watch?v=uGSCrymtZOQ).  For instance you'll notice that Box2D.XNA has a "MaxDistanceJoint" which is not in the original C++ Box2D.  This is needed to support a crane-like system as shown in Wayne the Brain.  In terms of perf, we had no reason to make changes because it ran at 60FPS on Xbox 360.

However, now that Wayne the Brain is wrapping up we will definitely be revisiting the engine for another round of perf tuning.  We want to start considering Windows Phone 7 perf.  So expect more in this area in the not too distant future.

 

Mar 22, 2010 at 6:36 PM
Edited Mar 22, 2010 at 6:38 PM
It runs great. The problem is the 360's primitive garbage collector. There's a game that just passed peer review called Stick 'Em Up you might want to check out. The game runs great - except that it stutters every few seconds.

Simple solution for World.Solve is to cache the working list. Instead of

Body[] stack = new Body[_bodyCount];

reuse an array that is a member variable of the class, growing it if required. Not a perfect solution, since it still allocates, but it will only allocate if the total bodies in the world has grown.

The second biggest change I made was recycling body objects. World.DestroyBody stores bodies in a list, CreateBody will use a body from that list first, and only allocate if it needs more. I did the same thing with the fixtures.

Priming the recycled body list helps avoid ever allocating. Since I've already got a maximum game entity count, I just fill the list with that many bodies, and creating a body almost never allocates.
Mar 25, 2010 at 1:28 PM

@blecki:

I implemented that exact solution some months ago when I recived the first version of Box2D.XNA. The implemented solution can be seen in Farseer Physics Engine 3.0 World.cs line 664.

I've not implemented pooling of bodies like you describe in your second change, I'm still thinking if it is necessary and whether I should let that kind of implementation be up to the users of the library or not. It is the same old discussion about removing bodies from the engine versus disabling them. - I still stick with the disable option.

Mar 31, 2010 at 6:49 AM

BTW, these allocations & many more have been eliminated with my latest change.  The only thing left is Contact/ContactEdge.

Apr 1, 2010 at 12:01 AM

Great! It's nice to see that just using  the library generates much less garbage.

 

But it's still not that great for an application the creates and destroys lots of bodies. It might be futile in my case, I'm usually not creating the same identical bodies all the time, so even if the body object doesn't get reallocated, it's fixtures probably will. Tuning it for my case is probably too invasive a change for a general-purpose library.

 

You can see what I'm using it for at http://jemgine.omnisu.com/

Apr 1, 2010 at 4:43 AM

Yeah, I'm still working on reducing garbage further.  I need to finish removing all the 'behind the scenes' garbage (from Contacts) and then I'll start thinking about reusing bodies/fixtures/shapes.  In the meantime, this is something that games can do at the application level.