Thanks for reading through it!

bearophile wrote:
Robert Fraser:
Attached, if you don't mind NO comments.

This is your code, I can see you have not used the union trick to reduce the 
memory used by each node that I suggested you:

        private static struct TreeNode
        {
                TreeNode* left;
                TreeNode* right;
            TreeNode* mid;
                K split;
                K[] key;
                V value;
        }

How does the union trick work exactly?

And it seems all nodes contain a value, not just the leaves.

I'm assuming that V.sizeof == (void*).sizeof. There's actually 12 bytes that are unused on all but nodes containing values, since the key is also cached in there. This could eliminated by keeping track of the current stack in the opApply methods, but that slows down iteration.

Non-leaf nodes can also have values. For example, if you have "var" = 5 and "var2" = 10, "r" will have a value and a mid.

the compiler wasn't unrolling the tail call<

I think still DMD isn't able to unroll tail calls.

Regarding the memory.d, in my implementation I have used a:
T[(MAX_BLOCK_BYTES / T.sizeof)] items;

you have used:
private void[BLOCK_SIZE] data = void;
memset(blk.data.ptr, 0, BLOCK_SIZE);

Not setting that void array (of uint? ubyte?) to void the compiler sets it to 
zero with a memset, so I don't understand what you have gained.

void[SIZE]; fails with an obscure error message... you need to initialize it to void.

And allocating an array of nodes offers a GC a chance to know what's inside the 
block of memory, so it's more compatible with better future GCs (it may be 
better even now).
It also allows for safer initializations of the struct fields, for example on 
some CPUs null can be != 0

I agree, but I wanted a generic construct that could also be used for allocating class instances.

Later I'll try to adapt your code to Phobos1.

Thanks!

Reply via email to