rbyd: Dropped special altn/alta encoding

altas, and to a lesser extend altns, are just too problematic for our
rbyd-append algorithm.

Main issue is these break our "narrowing" invariant, where each alt only
ever decreases the bounds.

I wanted to use altas to simplify lfsr_rbyd_appendcompaction, but
decided it wasn't worth it. Handling them correctly would require adding
a number of special cases to lfsr_rbyd_appendrat, adding complexity to
an already incredibly complex function.

---

Fortunately, we don't really need altns/altas on-disk, but we _do_ need
a way to mark alts as unreachable internally in order to know when we
can collapse alts when recoloring (at this point bounds information is
lost).

I was originally going to use the alt's sign bit for this, but it turns
out we already have this information thanks to setting jump=0 to assert
that an alt is unreachable. So no explicit flag needed!

This ends up saving a surprising amount of code for what is only a
couple lines of changes:

           code          stack          ctx
  before: 38512           2624          640
  after:  38440 (-0.2%)   2624 (+0.0%)  640 (+0.0%)
This commit is contained in:
Christopher Haster
2025-01-22 01:49:08 -06:00
parent ab26437e46
commit 68f0534dd0
6 changed files with 39 additions and 49 deletions
+24 -19
View File
@@ -1265,14 +1265,6 @@ static inline bool lfsr_tag_isgt(lfsr_tag_t tag) {
return tag & LFSR_TAG_GT;
}
static inline bool lfsr_tag_isa(lfsr_tag_t tag) {
return (tag & 0x1fff) == (LFSR_TAG_GT | 0);
}
static inline bool lfsr_tag_isn(lfsr_tag_t tag) {
return (tag & 0x1fff) == (LFSR_TAG_LE | 0);
}
static inline lfsr_tag_t lfsr_tag_isparallel(lfsr_tag_t a, lfsr_tag_t b) {
return (a & LFSR_TAG_GT) == (b & LFSR_TAG_GT);
}
@@ -1281,7 +1273,7 @@ static inline bool lfsr_tag_follow(
lfsr_tag_t alt, lfsr_rid_t weight,
lfsr_srid_t lower_rid, lfsr_srid_t upper_rid,
lfsr_srid_t rid, lfsr_tag_t tag) {
// null tags break the following logic for altns/altas
// null tags break the following logic for unreachable alts
LFS_ASSERT(lfsr_tag_key(tag) != 0);
if (lfsr_tag_isgt(alt)) {
@@ -1332,12 +1324,12 @@ static inline void lfsr_tag_trim(
LFS_ASSERT((lfsr_srid_t)weight >= 0);
if (lfsr_tag_isgt(alt)) {
*upper_rid -= weight;
if (upper_tag && !lfsr_tag_isa(alt)) {
if (upper_tag) {
*upper_tag = alt + 1;
}
} else {
*lower_rid += weight;
if (lower_tag && !lfsr_tag_isn(alt)) {
if (lower_tag) {
*lower_tag = alt;
}
}
@@ -3289,9 +3281,13 @@ static int lfsr_rbyd_p_flush(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// write out some number of alt pointers in our queue
for (int i = 0; i < count; i++) {
if (p[3-1-i].alt) {
// change to a relative jump at the last minute
// jump=0 represents an unreachable alt, we do write out
// unreachable alts sometimes in order to maintain the
// balance of the tree
LFS_ASSERT(p[3-1-i].jump || lfsr_tag_isblack(p[3-1-i].alt));
lfsr_tag_t alt = p[3-1-i].alt;
lfsr_rid_t weight = p[3-1-i].weight;
// change to a relative jump at the last minute
lfs_size_t jump = (p[3-1-i].jump)
? lfsr_rbyd_eoff(rbyd) - p[3-1-i].jump
: 0;
@@ -3335,8 +3331,8 @@ static void lfsr_rbyd_p_recolor(
if (p[1].alt) {
p[1].alt |= LFSR_TAG_R;
// alt-never? we can prune this now
if (lfsr_tag_isn(p[1].alt)) {
// unreachable alt? we can prune this now
if (!p[1].jump) {
p[1] = p[2];
p[2].alt = 0;
@@ -3708,16 +3704,25 @@ trunk:;
branch = branch_;
continue;
// convert unreachable non-root black alts into alt-nevers,
// if we prune these it would break the color balance of
// our tree
// mark unreachable non-root black alts as unreachable,
// we can't prune these or we risk breaking the color
// balance of our tree, but if we push a red up later we
// can get rid of them
// : :
// <b => nb
// .-'| .--'
// 3 4 3 4 x
} else {
alt = LFSR_TAG_ALT(LFSR_TAG_B, LFSR_TAG_LE, 0);
weight = 0;
alt = LFSR_TAG_ALT(
LFSR_TAG_B,
LFSR_TAG_LE,
(diverged && !(a_rid < b_rid || a_tag < b_tag))
? d_tag
: lower_tag);
LFS_ASSERT(weight == 0);
// we don't need to, but setting jump=0 asserts this
// alt is unreachable while also minimizing the the
// encoding
jump = 0;
}
}
+3 -6
View File
@@ -226,13 +226,10 @@ def tagrepr(tag, w=None, size=None, off=None):
' w%d' % w if w else '',
' %s' % size if size is not None else '')
elif tag & TAG_ALT:
return 'alt%s%s%s%s%s' % (
return 'alt%s%s 0x%03x%s%s' % (
'r' if tag & TAG_R else 'b',
'a' if tag & 0x0fff == 0 and tag & TAG_GT
else 'n' if tag & 0x0fff == 0
else 'gt' if tag & TAG_GT
else 'le',
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
'gt' if tag & TAG_GT else 'le',
tag & 0x0fff,
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size and off is not None
+3 -6
View File
@@ -272,13 +272,10 @@ def tagrepr(tag, w=None, size=None, off=None):
' w%d' % w if w else '',
' %s' % size if size is not None else '')
elif tag & TAG_ALT:
return 'alt%s%s%s%s%s' % (
return 'alt%s%s 0x%03x%s%s' % (
'r' if tag & TAG_R else 'b',
'a' if tag & 0x0fff == 0 and tag & TAG_GT
else 'n' if tag & 0x0fff == 0
else 'gt' if tag & TAG_GT
else 'le',
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
'gt' if tag & TAG_GT else 'le',
tag & 0x0fff,
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size and off is not None
+3 -6
View File
@@ -241,13 +241,10 @@ def tagrepr(tag, w=None, size=None, off=None):
' w%d' % w if w else '',
' %s' % size if size is not None else '')
elif tag & TAG_ALT:
return 'alt%s%s%s%s%s' % (
return 'alt%s%s 0x%03x%s%s' % (
'r' if tag & TAG_R else 'b',
'a' if tag & 0x0fff == 0 and tag & TAG_GT
else 'n' if tag & 0x0fff == 0
else 'gt' if tag & TAG_GT
else 'le',
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
'gt' if tag & TAG_GT else 'le',
tag & 0x0fff,
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size and off is not None
+3 -6
View File
@@ -229,13 +229,10 @@ def tagrepr(tag, w=None, size=None, off=None):
' w%d' % w if w else '',
' %s' % size if size is not None else '')
elif tag & TAG_ALT:
return 'alt%s%s%s%s%s' % (
return 'alt%s%s 0x%03x%s%s' % (
'r' if tag & TAG_R else 'b',
'a' if tag & 0x0fff == 0 and tag & TAG_GT
else 'n' if tag & 0x0fff == 0
else 'gt' if tag & TAG_GT
else 'le',
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
'gt' if tag & TAG_GT else 'le',
tag & 0x0fff,
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size and off is not None
+3 -6
View File
@@ -183,13 +183,10 @@ def tagrepr(tag, w=None, size=None, off=None):
' w%d' % w if w else '',
' %s' % size if size is not None else '')
elif tag & TAG_ALT:
return 'alt%s%s%s%s%s' % (
return 'alt%s%s 0x%03x%s%s' % (
'r' if tag & TAG_R else 'b',
'a' if tag & 0x0fff == 0 and tag & TAG_GT
else 'n' if tag & 0x0fff == 0
else 'gt' if tag & TAG_GT
else 'le',
' 0x%x' % (tag & 0x0fff) if tag & 0x0fff != 0 else '',
'gt' if tag & TAG_GT else 'le',
tag & 0x0fff,
' w%d' % w if w is not None else '',
' 0x%x' % (0xffffffff & (off-size))
if size and off is not None