Ternary Search Trees
Robert Fraser
fraserofthenight at gmail.com
Fri Apr 17 18:18:10 PDT 2009
bearophile wrote:
> OK, now the code works. Besude the TST struct I have created this helper struct that keeps a pool of tree nodes:
>
> struct StructPool(TyStruct, int MAX_BLOCK_SIZE_BYTES=1 << 14) {
> static assert(MAX_BLOCK_SIZE_BYTES >= 1);
>
> struct Block {
> // Block is not too much big nor too much small
> const int MAXB = MAX_BLOCK_SIZE_BYTES / TyStruct.sizeof;
> const int SIZE = MAXB >= 1 ? MAXB : 1;
> TyStruct[StructPool.Block.SIZE] structs;
> }
>
> static TyStruct* next_free_struct_ptr, last_struct_ptr;
> static Block*[] blocks;
>
> static TyStruct* newStruct() {
> if (StructPool.next_free_struct_ptr >= StructPool.last_struct_ptr) {
> // then add new block
>
> // this whole new block gets scanned by the GC even if you need only 1 node
> StructPool.blocks.length = StructPool.blocks.length + 1;
> StructPool.blocks[$-1] = new Block;
>
> StructPool.next_free_struct_ptr = StructPool.blocks[$-1].structs.ptr;
> StructPool.last_struct_ptr = StructPool.next_free_struct_ptr + Block.SIZE;
>
> }
>
> return StructPool.next_free_struct_ptr++;
> }
>
> /// deallocate blocks of structs
> static void free() {
> foreach (block_ptr; StructPool.blocks)
> delete block_ptr;
> StructPool.blocks[] = null;
> StructPool.blocks.length = 0;
> StructPool.next_free_struct_ptr = null;
> StructPool.last_struct_ptr = null;
> }
> }
>
> alias StructPool!(TST!(char)) TSTpool;
>
> (I have used to static pointers, one single index to the last filled up struct is also enough.)
> That newStruct() is fast, about as class allocations in Java :-)
>
> It's not nice code yet, with that external alias and so on, but it seems to work and it almost halves the total allocation time of a big ternary search tree (but despite the improve cache coherence the positive lookups into such TST are about as fast as in a normally allocated TST, maybe because the D GC packs the nodes closely in memory anyway). So I think in certain situations it can be useful.
>
> Now I'm trying to make the code nicer and less bug-prone, for example turning that StructPool struct into a template mixin that I can use to add such pool capability to other structs too that need to allocate many small structs and to deallocate them all at the same time. But so far I have had the same kinds errors I have shown in the two past posts.
>
> Bye,
> bearophile
Cool, thanks for posting this... Why is the default block size so
freaking huge (16kb)?
More information about the Digitalmars-d
mailing list