Rough draft of general btree implementation, needs work

This implements a common B-tree using rbyd's as inner nodes.

Since our rbyds actually map to sorted arrays, this fits together quite
well.

The main caveat/concern is that we can't rely on strict knowledge on the
on-disk size of these things. This first shows up with B-tree insertion,
we can't split in preparation to insert as we descend down the tree.

Normally, this means our B-tree would require recursion in order to keep
track of each parent as we descend down our tree. However, we can
avoid this by not storing our parent, but by looking it up again on each
step of the splitting operation.

This brute-force-ish approach makes our algorithm tail-recursive, so
bounded RAM, but raises our runtime from O(logB(n)) to O(logB(n)^2)

That being said, O(logB(n)^2) is still sublinear, and, thanks to
B-tree's extremely high branching factor, may be insignificant.
This commit is contained in:
Christopher Haster
2023-02-22 00:43:51 -06:00
parent a20625be7c
commit 1709aec95b
3 changed files with 929 additions and 61 deletions
+9 -3
View File
@@ -62,6 +62,12 @@ def tagrepr(tag, id, w, size, off=None):
id,
' w%d' % w if w is not None else '',
size)
elif tag == 0x0810:
return 'block id%d %d' % (id, size)
elif tag == 0x0820:
return 'btree id%d %d' % (id, size)
elif tag == 0x0830:
return 'branch id%d %d' % (id, size)
elif (tag & ~0xff2) == 0x2000:
return '%suattr 0x%02x%s%s' % (
'rm' if tag & 0x2 else '',
@@ -180,7 +186,8 @@ def show_log(block_size, data, rev, off, *,
grow = None
colors = ['']
colors_i = 0
lifetimes = [(0, 0, -1, weights.copy(), colors.copy())]
# note these slices are also copying the arrays
lifetimes = [(0, 0, -1, weights[:-1], colors[:-1])]
j_ = 4
while j_ < (block_size if args.get('all') else off):
@@ -190,7 +197,6 @@ def show_log(block_size, data, rev, off, *,
if (tag & 0xe) <= 0x4:
j_ += size
# note these slices are also copying the arrays
if grow is not None:
if (tag & ~0x3f0) == 0x0400 and id == grow[1]:
i, p = index(weights, id)
@@ -241,7 +247,7 @@ def show_log(block_size, data, rev, off, *,
else '\\ ' if g > 0 and id < a
else '\'' if g < 0 and id >= a and id < b
else '/ ' if g < 0 and id < a
else '* ' if not tag & 0x8 and id >= a and id < b
else '* ' if id >= a and id < b
else '| ',
'\x1b[m' if color else '')
for (a, b), c in zip(ranges(weights), colors)),