From 079f4f67fb55708ac0a0d653f52464a987580f76 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 30 Mar 2024 01:52:16 -0500 Subject: [PATCH] rbyd-rr: Eagerly prune unreachable root alts In a traditional B-tree/2-3-4 tree/red-black tree, balance is maintained by enforcing a set of rules such that no operation changes the balance of the tree. In such a ruleset, you quickly learn that the only way to actually change the height of the tree is through the root, since the root is the only node shared by all branches of the tree. This is why B/2-3-4/red-black insert/removes usually end in "and then if you hit the root of the tree, increase/decrease the height by one". Our range removal algorithm is a bit different in that we aren't guaranteed to reach the root, the requested range could be empty after all, but we also aren't _prohibited_ from decreasing the height of the tree if it only involves removing the root. Removing the root still maintains the 2-3-4 structure and balance of our tree. --- This commit adds opportunistic root pruning to our set of possible pruning conditions. This also tweaks diverging-lower pruning to take advantage of root pruning. Since we prune the entire diverging-lower path, we can pretend diverging-lower alts are prunable roots up until we find the diverging alt. This leads to a bit nicer code since root pruning is so simple. This actually ended up revealing an issue with how we indirectly trigger diverged pruning by triming diverging alts: Trimming works, but we also need to zero any weight, or else later calculations get all screwy... I guess the extra coverage from reusing logic is a plus. Code changes: code stack before: 34236 2864 after: 34256 (+0.1%) 2864 (+0.0%) --- lfs.c | 109 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/lfs.c b/lfs.c index 0969625f..be8ee0be 100644 --- a/lfs.c +++ b/lfs.c @@ -2910,78 +2910,71 @@ again:; jump = branch - jump; lfs_size_t branch_ = branch + d; - // progress diverging state machine? - if (!lfsr_d_isdiverged(d_state)) { - // do bounds want to take different paths? begin diverging - bool diverge - = lfsr_tag_follow2(alt, weight, + // do bounds want to take different paths? begin diverging + if (!lfsr_d_isdiverged(d_state) + && (lfsr_tag_follow2(alt, weight, p_alts[0], p_weights[0], lower_rid, upper_rid, a_rid, a_tag) ^ lfsr_tag_follow2(alt, weight, p_alts[0], p_weights[0], lower_rid, upper_rid, - b_rid, b_tag); + b_rid, b_tag))) { + LFS_ASSERT(d_state != LFSR_D_NOTDIVERGING); - // skip common alts on lower pass and the diverging alt - // itself on both paths - if (d_state == LFSR_D_DIVERGINGLOWER || diverge) { - LFS_ASSERT(d_state != LFSR_D_NOTDIVERGING); + // transition to the diverged state + // + // note that if red alt diverged if would have been + // caught on the previous pass + d_state = lfsr_d_diverge(d_state); - if (lfsr_tag_follow2( - alt, weight, + if (lfsr_tag_follow2( + alt, weight, + p_alts[0], p_weights[0], + lower_rid, upper_rid, + a_rid, a_tag)) { + lfsr_tag_flip2( + &alt, &weight, p_alts[0], p_weights[0], - lower_rid, upper_rid, - a_rid, a_tag)) { - lfsr_tag_flip2( - &alt, &weight, - p_alts[0], p_weights[0], - lower_rid, upper_rid); - lfs_swap32(&jump, &branch_); - } - lfsr_tag_trim2( - alt, weight, - p_alts[0], p_weights[0], - &lower_rid, &upper_rid, - &lower_tag, &upper_tag); - - // transition to the diverged state - // - // note that if red alt diverged if would have been - // caught on the previous pass - if (diverge) { - d_state = lfsr_d_diverge(d_state); - - // stitch together diverged branches - if (d_state == LFSR_D_DIVERGEDUPPER) { - err = lfsr_rbyd_p_push(lfs, rbyd, - p_alts, p_weights, p_jumps, - LFSR_TAG_ALT( - LFSR_TAG_LE, - LFSR_TAG_B, - d_tag), - d_rid - lower_rid + weight, - d_branch); - if (err) { - return err; - } - } - } - - branch = branch_; - continue; + lower_rid, upper_rid); + lfs_swap32(&jump, &branch_); } + lfsr_tag_trim2( + alt, weight, + p_alts[0], p_weights[0], + &lower_rid, &upper_rid, + &lower_tag, &upper_tag); + + // stitch together diverged branches + if (d_state == LFSR_D_DIVERGEDUPPER) { + err = lfsr_rbyd_p_push(lfs, rbyd, + p_alts, p_weights, p_jumps, + LFSR_TAG_ALT( + LFSR_TAG_LE, + LFSR_TAG_B, + d_tag), + d_rid - lower_rid + weight, + d_branch); + if (err) { + return err; + } + } + + branch = branch_; + continue; } // trim unreachable diverged alts so they end up pruned - if (lfsr_d_isdiverged(d_state) + if ((lfsr_d_isdiverged(d_state) && (d_state == LFSR_D_DIVERGEDUPPER) ^ lfsr_tag_isgt(alt) ^ lfsr_tag_follow2( alt, weight, p_alts[0], p_weights[0], lower_rid, upper_rid, - a_rid, a_tag)) { + a_rid, a_tag)) + // this includes all diverging-lower alts + || d_state == LFSR_D_DIVERGINGLOWER) { if (lfsr_tag_follow2( alt, weight, p_alts[0], p_weights[0], @@ -2997,6 +2990,7 @@ again:; alt, weight, &lower_rid, &upper_rid, &lower_tag, &upper_tag); + weight = 0; } // prune? @@ -3034,8 +3028,13 @@ again:; branch_ = branch; lfsr_rbyd_p_pop(p_alts, p_weights, p_jumps); - // make unreachable black alts alt-nevers, if we prune these - // it would break the coloring of our tree + // collapse unreachable _root_ alts + } else if (!p_alts[0] && d_state != LFSR_D_DIVERGEDLOWER) { + branch = branch_; + continue; + + // make unreachable non-root black alts alt-nevers, if we + // prune these it would break the coloring of our tree } else { alt = LFSR_TAG_ALT(LFSR_TAG_LE, LFSR_TAG_B, 0); weight = 0;