• TOC
  • GigaMess
  • CodeTips
  • Stuff
  • Links
  • Contact

Fast new and delete with Boost's pools

First, you need to download Boost, a free C++ library collection. It has a nice set of memory pool templates. The basic idea behind memory pool is that instead of allocating hundreds of small objects individually from the heap, you allocate a large block of memory which will hold several small objects of some constant size. The benefits are smaller memory usage and gained speed. More explanation of pools on the Boost site.

The Boost pools are a bit cumbersome to use as they are, but I made two utility classes that let you use them easily with whatever class you wish.

1. FastPODAllocator <gms/FastPODAllocator.h>

Suppose you have a class like this:

//old class, slow new/delete
class A {
  int x, y;
};

Now, to make that class to have superfast new/delete (over 10 times faster for a class that small!), all you need to do is this:

//new class, fast new/delete
class A : public gms::FastPODAllocator<A> {
  int x, y;
};

POD in the name comes from 'plain old data' which means structures that don't behave polymorphically. Thus, using FastPODAllocator<> with a class that has subclasses would be a mistake (it would allocate wrong amount of memory for subclasses). Notice that you must feed the FastPODAllocator template with the name of your class. That way it can create a memory pool with appropriate size.

2. FastAllocator <gms/FastAllocator.h>

If you want to have some polymorphism/subclassing going on, you must use FastAllocator instead:

class B : public gms::FastAllocator
{
  int i, j;
};

class D : public B {
  int x, y;
};

Notice the non-existence of template argument. FastAllocator contains several pools (64) of different sizes and selects the appropriate one for the (de)allocatable object. If objects are bigger than 64 bytes, FastAllocator uses the normal ::operator new(). You can change the limit, 64, by defining MAX_SMALL_OBJECT_SIZE as some other number than 64. Loki library uses the same define for the exact same purpose, so I decided to adapt to it.

So why would anyone use FastPODAllocator when FastAllocator is so much better? Speed is the answer, naturally. FastAllocator has a virtual destructor so any class derived from it must pay the cost of vtable pointer. FastAllocator is also slightly more complex. In my tests, FastPODAllocator was over twice as fast as FastAllocator. It's uses are pretty limited, though.

FastAllocator and FastPODAllocator override new and delete operations to do their job. Download both of them, because I know you want to. FastPODAllocator.h is extremely simple, FastAlloctor.h has a bit more going on in there but you should be able to grasp the concept from the comments. FastAllocator's PoolManager was influenced by the book Modern C++ Design (highly recommended), which oddly introduced a significantly slower pool implementation than Boost and my wrapper classes. That implementation is available through Loki.

Also note:

  • Fast(POD)Allocator mostly boosts the creation/deletion speed of small objects. It doesn't affect much on big ones
  • Fast(POD)Allocator is not thread safe. Creating two "FastAllocated objects" at the same time from two different threads leads to undefined behaviour. However, it should be easy to add appropriate synchronization to the implementation.
  • Since all the small objects of certain size are reserved from a shared memory pool, cache coherency may not be very good with this solution. It may be worth the trouble to use Boost's pools manually in some occasions, to ensure that objects which are usually accessed in tight succession, also lie close to each other in memory.