Commit 6ea5920a authored by Kirill Smelkov's avatar Kirill Smelkov

X xbtree: Less copy/garbage in RangedKeySet ops

rebuild tests ~75 -> ~73s.
parent 8f0e37f2
...@@ -34,7 +34,7 @@ type KeyRange struct { ...@@ -34,7 +34,7 @@ type KeyRange struct {
hi_ Key // NOTE _not_ hi) to avoid overflow at ∞; hi = hi_ + 1 hi_ Key // NOTE _not_ hi) to avoid overflow at ∞; hi = hi_ + 1
} }
// RangedKeySet is set of Keys with adjacent keys coaleced into Ranges. // RangedKeySet is set of Keys with adjacent keys coalesced into Ranges.
// //
// Zero value represents empty set. // Zero value represents empty set.
type RangedKeySet struct { type RangedKeySet struct {
...@@ -109,20 +109,14 @@ func (S *RangedKeySet) AddRange(r KeyRange) { ...@@ -109,20 +109,14 @@ func (S *RangedKeySet) AddRange(r KeyRange) {
if (jhi - ilo) > 1 { if (jhi - ilo) > 1 {
lo := S.rangev[ilo].lo lo := S.rangev[ilo].lo
hi_ := S.rangev[jhi-1].hi_ hi_ := S.rangev[jhi-1].hi_
S.rangev = append( vReplaceSlice(&S.rangev, ilo,jhi, KeyRange{lo,hi_})
S.rangev[:ilo], append([]KeyRange{
KeyRange{lo, hi_}},
S.rangev[jhi:]...)...)
debugfRSet("\tmerge S[%d:%d]\t-> %s\n", ilo, jhi, S) debugfRSet("\tmerge S[%d:%d]\t-> %s\n", ilo, jhi, S)
} }
jhi = -1 // no longer valid jhi = -1 // no longer valid
// if [r.lo,r.hi) was outside of any entry - create new entry // if [r.lo,r.hi) was outside of any entry - create new entry
if r.hi_ < S.rangev[ilo].lo { if r.hi_ < S.rangev[ilo].lo {
S.rangev = append( vInsert(&S.rangev, ilo, r)
S.rangev[:ilo], append([]KeyRange{
r},
S.rangev[ilo:]...)...)
debugfRSet("\tinsert %s\t-> %s\n", r, S) debugfRSet("\tinsert %s\t-> %s\n", r, S)
} }
...@@ -140,20 +134,16 @@ func (S *RangedKeySet) AddRange(r KeyRange) { ...@@ -140,20 +134,16 @@ func (S *RangedKeySet) AddRange(r KeyRange) {
// and check if we should merge it with right/left neighbours // and check if we should merge it with right/left neighbours
if ilo+1 < len(S.rangev) { // right if ilo+1 < len(S.rangev) { // right
if S.rangev[ilo].hi_+1 == S.rangev[ilo+1].lo { if S.rangev[ilo].hi_+1 == S.rangev[ilo+1].lo {
S.rangev = append( vReplaceSlice(&S.rangev, ilo,ilo+2,
S.rangev[:ilo], append([]KeyRange{ KeyRange{S.rangev[ilo].lo, S.rangev[ilo+1].hi_})
KeyRange{S.rangev[ilo].lo, S.rangev[ilo+1].hi_}},
S.rangev[ilo+2:]...)...)
debugfRSet("\tmerge right\t-> %s\n", S) debugfRSet("\tmerge right\t-> %s\n", S)
} }
} }
if ilo > 0 { // left if ilo > 0 { // left
if S.rangev[ilo-1].hi_+1 == S.rangev[ilo].lo { if S.rangev[ilo-1].hi_+1 == S.rangev[ilo].lo {
S.rangev = append( vReplaceSlice(&S.rangev, ilo-1,ilo+1,
S.rangev[:ilo-1], append([]KeyRange{ KeyRange{S.rangev[ilo-1].lo, S.rangev[ilo].hi_})
KeyRange{S.rangev[ilo-1].lo, S.rangev[ilo].hi_}},
S.rangev[ilo+1:]...)...)
debugfRSet("\tmerge left\t-> %s\n", S) debugfRSet("\tmerge left\t-> %s\n", S)
} }
} }
...@@ -204,38 +194,27 @@ func (S *RangedKeySet) DelRange(r KeyRange) { ...@@ -204,38 +194,27 @@ func (S *RangedKeySet) DelRange(r KeyRange) {
} }
// [ilo+1:jhi-1] should be deleted // [ilo+1:jhi-1] should be deleted
// [ilo] and [jhi-1] overlap with [r.lo,r.hi) - they shuold be deleted, or shrinked, // [ilo] and [jhi-1] overlap with [r.lo,r.hi) - they should be deleted, or shrinked,
// or split+shrinked if ilo==jhi-1 and r is inside [ilo] // or split+shrinked if ilo==jhi-1 and r is inside [ilo]
if jhi-ilo == 1 && S.rangev[ilo].lo < r.lo && r.hi_ < S.rangev[ilo].hi_ { if jhi-ilo == 1 && S.rangev[ilo].lo < r.lo && r.hi_ < S.rangev[ilo].hi_ {
x := S.rangev[ilo] x := S.rangev[ilo]
S.rangev = append( vInsert(&S.rangev, ilo, x)
S.rangev[:ilo], append([]KeyRange{
x, x},
S.rangev[ilo+1:]...)...)
jhi++ jhi++
debugfRSet("\tpresplit copy %s\t-> %s\n", x, S) debugfRSet("\tpresplit copy %s\t-> %s\n", x, S)
} }
if S.rangev[ilo].lo < r.lo { // shrink left if S.rangev[ilo].lo < r.lo { // shrink left
S.rangev = append( S.rangev[ilo] = KeyRange{S.rangev[ilo].lo, r.lo-1}
S.rangev[:ilo], append([]KeyRange{
KeyRange{S.rangev[ilo].lo, r.lo-1}},
S.rangev[ilo+1:]...)...)
ilo++ ilo++
debugfRSet("\tshrink [%d] left\t-> %s\n", ilo, S) debugfRSet("\tshrink [%d] left\t-> %s\n", ilo, S)
} }
if r.hi_ < S.rangev[jhi-1].hi_ { // shrink right if r.hi_ < S.rangev[jhi-1].hi_ { // shrink right
S.rangev = append( S.rangev[jhi-1] = KeyRange{r.hi_+1, S.rangev[jhi-1].hi_}
S.rangev[:jhi-1], append([]KeyRange{
KeyRange{r.hi_+1, S.rangev[jhi-1].hi_}},
S.rangev[jhi:]...)...)
jhi-- jhi--
debugfRSet("\tshrink [%d] right\t-> %s\n", jhi-1, S) debugfRSet("\tshrink [%d] right\t-> %s\n", jhi-1, S)
} }
if (jhi - ilo) > 0 { if (jhi - ilo) > 0 {
S.rangev = append( vDeleteSlice(&S.rangev, ilo,jhi)
S.rangev[:ilo],
S.rangev[jhi:]...)
debugfRSet("\tdelete S[%d:%d]\t-> %s\n", ilo, jhi, S) debugfRSet("\tdelete S[%d:%d]\t-> %s\n", ilo, jhi, S)
} }
...@@ -414,3 +393,32 @@ func debugfRSet(format string, argv ...interface{}) { ...@@ -414,3 +393,32 @@ func debugfRSet(format string, argv ...interface{}) {
} }
fmt.Printf(format, argv...) fmt.Printf(format, argv...)
} }
// ---- slice ops ----
// vInsert inserts r into *pv[i].
func vInsert(pv *[]KeyRange, i int, r KeyRange) {
v := *pv
v = append(v, KeyRange{})
copy(v[i+1:], v[i:])
v[i] = r
*pv = v
}
// vDeleteSlice deletes *pv[lo:hi].
func vDeleteSlice(pv *[]KeyRange, lo,hi int) {
v := *pv
n := copy(v[lo:], v[hi:])
v = v[:lo+n]
*pv = v
}
// vReplaceSlice replaces *pv[lo:hi] with r.
func vReplaceSlice(pv *[]KeyRange, lo,hi int, r KeyRange) {
v := *pv
n := copy(v[lo+1:], v[hi:])
v[lo] = r
v = v[:lo+1+n]
*pv = v
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment