Wednesday, December 21, 2005

The dangers of vector

Overall the STL has been a big win in X-Plane, but as I’ve worked on performance and optimization over the last week, some of the biggest wins have been from losing the STL and going back to older, simpler C structures.

The STL vector is a dangerous thing - most of the time it’s fast, efficient, easy to use, and simple enough that the compiler optimizes right through it. But when you have to build one up incrementally the performance is terrible.

The STL list can build up incrementally, but then for small objects you spend a ton on overhead for node pointer storage, etc.

So two things have worked well:

1. Simply adding a “next” pointer to small structures to turn them into an intrinsically linked list.

2. Using a memory sub-allocator. Our sub-allocator grabs a large chunk of memory, doles out small pieces (without tracking allocations — a high water mark just grows and we grab a new big block when we need one), and then the big blocks can be nuked en masse when we’re done with the whole subsystem. (Thanks to one of our users who I won’t “out” for suggesting this and design!)

In X-Plane we have to build up a lot of structures whose final sizes are difficult to determine, so these two ideas work well together; the sub-allocator is very fast for small allocations (the common case can even be inlined), and the overhead for the next pointer is reasonably painless. This scheme saved 25 MB just by applying it to the physical terrain triangle mesh.

(Another advantage of the intrinsically linked list: no need for a copy constructor or operator=, which might be difficult or undesirable to implement for a very complex heavyweight object.)

A final thought: putting 2 GB of RAM in your devepment machine might seem like a good idea, but it can be dangerous. Before I got the above scheme working my previous attempts to reorganize the code using STL vectors and lists bloated memory usage by 200 MB, and the performance hit was zero — the dangers of a G5.