From b7216e783d7113a58e9e2eea9fec665aad28e23f Mon Sep 17 00:00:00 2001 From: Johannes Kimmel Date: Mon, 13 Nov 2023 23:50:26 +0100 Subject: [PATCH] correctly precalculate the minimum free prefix length on alloc, so recalculation can be skipped for deeply nested inserts --- ipalloc/ipalloc.go | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/ipalloc/ipalloc.go b/ipalloc/ipalloc.go index 69860d1..e7ab035 100644 --- a/ipalloc/ipalloc.go +++ b/ipalloc/ipalloc.go @@ -112,12 +112,14 @@ func (t *tree) Alloc(bits int) *tree { return nil } + tofix := best + // the first insert can be into a new hi branch if best.lo != nil { best.hi = &tree{ prefix: SplitPrefixHi(best.prefix), parent: best, - minfreelen: best.prefix.Bits() + 1, + minfreelen: best.prefix.Bits() + 2, } best = best.hi } @@ -127,12 +129,14 @@ func (t *tree) Alloc(bits int) *tree { best.lo = &tree{ prefix: SplitPrefixLo(best.prefix), parent: best, - minfreelen: best.prefix.Bits() + 1, + minfreelen: best.prefix.Bits() + 2, } best = best.lo } - best.fixMinFreeAll() + best.fixMinFree() + tofix.fixMinFreeAll() + return best } @@ -142,26 +146,25 @@ func (t *tree) fixMinFree() { } if t.Leaf() { t.minfreelen = t.prefix.Addr().BitLen() + 1 + return } lofree := t.lo.calcfreelen(t) hifree := t.hi.calcfreelen(t) minfreelen := max(min(lofree, hifree), t.prefix.Bits()+1) - if t.minfreelen != minfreelen { - //log.Printf("lo:%v, hi:%v\n", fixfree.lo == nil, fixfree.hi == nil) - //log.Printf("Fixing space for %q, lo: %d, hi: %d, old: %d, new: %d", fixfree.prefix, lofree, hifree, fixfree.minfreelen, minfreelen) - t.minfreelen = minfreelen - } + //if t.minfreelen != minfreelen { + // log.Printf("lo:%v, hi:%v\n", t.lo == nil, t.hi == nil) + // log.Printf("Fixing space for %q, lo: %d, hi: %d, old: %d, new: %d", t.prefix, lofree, hifree, t.minfreelen, minfreelen) + //} + + t.minfreelen = minfreelen } func (t *tree) fixMinFreeAll() { if t == nil { return } - if t.Leaf() { - t.minfreelen = t.prefix.Addr().BitLen() + 1 - } - fixfree := t.parent + fixfree := t for fixfree != nil { fixfree.fixMinFree()