Sidor

måndag 2 januari 2012

w3d1: Merging nibbles

Chunks with nibbles or one nibble per chunk?
Nomenclature:
Block = info and free lists for chunks of size k
Chunk = two nibbles, a and b, each of size k
Nibble = a memory block of size k
k = represents size in bytes, calculated by MIN_BLOCK_SIZE*2^k

Having A and B inside a chunk was easiest thing instead of returning two chunks, however, when merging nibbles that come from two different chunks (i.e. merging a B | A' b'), first and second's parents will be locked-up as follows in scenario 1.

p->a => c1->a, c1->b

p->b => c2->a, c2->b

release(c1->b), release(c2->a) => new parent chunk p2 can be created

At this point, p->a will be used as c1->a and p->b will be used as c2->b. The new p2 contains a full k-sized chunk. There are now two (k-1) chunks and one k chunk.

Scenario 2, in which chunks only have one memory blob instead of A and B:

p1->mem => c1->mem, c2->mem

p2->mem => c3->mem, c4->mem

release(c2->mem), release(c3->mem) => new parent chunk p3 can be created

p1->mem blocked by c1

p2->mem blocked by c4

My fear that this would lead to bits of memory never being restored (blocked by new parent chunk) was unfounded, since the same thing will happen in both scenarios. The advantage of not having A/B in one chunk is the somewhat easier management.

Merging nibbles to a new chunk
Until now there has been a relationship between parent and child chunks, i.e. p->a = c1->a, c1->b. However, as discussed in the above scenario, partially restoring the parent and creating a new would look like this:

This because p->a and p->b are only partially free (p->a's first half and p->b's second half) and cannot be used to create new child chunks, and becase of that, the flags are only useful if/when they're eventually combined, i.e. A_SECOND_HALF_USED|A_FIRST_HALF_USED. While possible, the occurance is most likely too rare to be justified the extra logic and memory for book keeping. Instead, the relationship between the parent and the child is ignored, and the flags are still A_SPLIT, B_SPLIT, A_USED and B_USED. The parent chunk will continue to hold A_SPLIT and B_SPLIT, and the new parent chunk will have blank flags, ready for use. Then, at an appropriate point in time (alloc? free? compact?), each chunk can be checked for children, and if needed, discarded.

In other words, a new parent will be created on each merge with no respect to the previous parent of the merged nibbles, except for the case when the nibbles are from the same chunk. Garbage collection happens at a later point, to make logic simpler.