A long day yesterday - left the house at 6:30am and got
home at 8:30pm - 14 hours. But, hey, when your wife phones
and says she won't be home till late, it's a perfect
opportunity to get in a few more hours.
I was on a roll anyway. I integrated the new bitmapped
memory manager (allocator and garbage collector) and it
worked! I've had this finished for a while but I've been
too chicken to drop it in. It underlies everything and
bugs at this level can be both catastrophic and elusive.
Just what you don't need. But it seems solid. Perhaps the
XP (extreme programming) techniques (simple incremental
development and automated tests) really work. And the
performance seems at least as good as the old stuff, and
probably better. It should be much more efficient space-
wise. Minimum allocation is 8 bytes instead of 16. (And
there are a surprising number of these tiny objects - e.g.
after startup, about 2000 out of 7000 objects are 8 bytes
or less!) And there is *no* overhead on the blocks
themselves (i.e. no "header" or "trailer"). The only space
overhead is the bitmaps. Each bit in the bitmaps controls
8 bytes of heap space, so each bitmap is 1/64 or roughly
1.5% overhead. There are three bitmaps (one to mark block
boundaries, one to use for mark/sweep, and one to designate
non-pointer blocks) so the overhead is about 4.5%. Most
memory managers have an overhead of 4 or 8 bytes per
block. On small blocks (the majority in a system like
Suneido) this can amount to as much as 25% space overhead.
The old memory manager also used a much smaller set of
block sizes, so there was more wastage from having to use
larger blocks than strictly necessary. And it also kept
separate memory pages for each size, so there was also
wastage per size. The new allocator is not page based, it
simply allocates consecutive memory locations (very fast)
and by its nature, the bitmapped garbage collection
automatically coalesces all the free space, greatly
reducing fragmentation. All in all it seems like a great
approach. (You might think that these days, with memory
plentiful, space efficiency is not important. But because
of caching and virtual memory, it can have a direct effect
on speed.)
The new memory manager also supports "non-pointer"
allocations. i.e. when you alloc something like a string,
that you know will never contain pointers to other heap
memory, you can tell this to the memory manager and then it
doesn't need to scan these blocks during garbage
collection. I made a few changes in the code so strings,
numbers, dates, and compiled code are non-pointer. This
resulted in about half of the heap being non-pointer,
thereby cutting the garbage collection scanning in half.
"finalization" is also supported. You can register a
pointer with the memory manager and when the memory it
points to is garbage collected (i.e. no more references to
it) instead of being free'd it is added to a queue. Then I
added an abstract SuFinalize base class (derived from
SuValue) that registers instances when they are created.
It has a virtual "finalize" method that derived concrete
classes define to release their resources. Then in
Suneido's main message loop, if there are no messages
waiting it removes values from the queue and calls finalize
on them. I modified SuFile to derive from SuFinalize, and
renamed it's close method to finalize. Voila, files are
now automatically closed if you forget to do it. Of
course, there's no guarantee on the timing of
finalization. Reference counting can detect unreferenced
objects immediately and predictably. But conservative
garbage collection is not quite so predictable. Often,
spurious pointers to objects will keep them "alive" for
some time after they are actually "dead". But at least you
have some assurance that resources will not "leak"
indefinitely. Now I have to modify Suneido's
other "resource holding" values to use this facility - e.g.
Transaction, Cursor, Image. Windows "handles" will take a
little more work because currently they're just treated as
integers. I'll have to define a Handle type and change the
dll definitions. But this will be an improvement anyway as
it will provide some type safety (i.e. stop you from
passing any old number as a handle).
Had a great bike ride to work this morning - it was cold,
windy, cloudy, and snowing - brisk, you might say. To
understand why I would call that "great", you need to know
that I leave in three weeks to lead a mountain climbing
expedition to an 8000m mountain in Tibet called
Shishapangma. So besides the physical training, I'm
working on mentally training myself to enjoy "interesting"
conditions :-) I've been so wrapped up in Suneido that I'm
feeling a little "separation anxiety". But I need the
break and I'm looking forward to a simpler, more physical
challenge, with a well defined goal and a clear definition
of "success".
Anyway, time to get to work - lots to do!