TempAlloc and druntime GC

dsimcha dsimcha at yahoo.com
Sun Jan 18 12:32:56 PST 2009


For those of you who aren't familiar with TempAlloc, it's a region-based
memory allocator that's essentially a second stack for allocating memory in a
last in, first out manner.  It is based on an idea proposed on this newsgroup
a few months back by Andrei under the name SuperStack, and was later
implemented by me.  The goal is to provide fast thread-local pointer-bumping
memory allocation for objects whose lifetime is bound to a scope, while
allowing the whole heap, instead of the relatively limited call stack space,
to be used.  According to some benchmarks I've done, TempAlloc can be anywhere
between 30% and 10s of times faster than the druntime GC allocator, depending
on several factors, the biggest being lock contention for the druntime
allocator.

TempAlloc's biggest weakness is that nothing allocated by TempAlloc is scanned
by the GC, making it impossible to safely store the only reference to
GC-allocated objects inside TempAlloc-allocated space.  I've been using
TempAlloc in my own personal projects for a while now, and have not found this
to be a significant limitation in practice.  Usually, if I'm using TempAlloc,
the whole point is to avoid generating GC heap activity within the function
I'm working in, meaning that I don't create any new GC-allocated objects in
that function.  If the objects I were created before calling that function,
there's another reference to them somewhere.  However, for people who are not
as familiar with how TempAlloc is implemented, or with how GC is implemented,
it may be easy to screw up, making TempAlloc a shoe with a gun built in and
probably unsuitable for inclusion in Phobos or Tango.

I've been thinking about how to deal with this issue and make TempAlloc safe
enough for inclusion in the standard library.  Since it works by allocating
large (currently 4 MB) regions from the C heap, and then sub-allocating these
regions to its clients, simply scanning these whole chunks is simply not a
reasonable option, as it would lead to way too many false pointers.  Using the
GC's addRegion/removeRegion interface at every TempAlloc allocation is also
not a reasonable option, as this operation requires a lock and would negate
any performance gains from using TempAlloc instead of the GC heap.  The only
alternative I see is to make the GC aware of TempAlloc at a very low level.
I've looked at the GC code and this doesn't look terribly hard to do.  Using
some bit twiddling tricks, I can do the bookkeeping to determine which
TempAlloc allocated objects should be scanned by the GC w/o any additional
space overhead.

The downside to this is that TempAlloc would be very tightly coupled to
druntime. Furthermore, if Sean and the other druntime maintainers decided they
didn't like my patch, my effort will be wasted.  Therefore, I'd like to get
some feedback before I bother doing anything.  Do you think that TempAlloc is
universally useful enough to belong in the standard library?  If so, do you
believe that it is only suitable for inclusion if it can be made safe w/
respect to storing the only reference to GC-allocated objects?  If so, is it
worth tightly coupling it to the GC, and should I start working on this and
submit a patch to druntime?



More information about the Digitalmars-d mailing list