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 {
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.
type RangedKeySet struct {
......@@ -109,20 +109,14 @@ func (S *RangedKeySet) AddRange(r KeyRange) {
if (jhi - ilo) > 1 {
lo := S.rangev[ilo].lo
hi_ := S.rangev[jhi-1].hi_
S.rangev = append(
S.rangev[:ilo], append([]KeyRange{
KeyRange{lo, hi_}},
S.rangev[jhi:]...)...)
vReplaceSlice(&S.rangev, ilo,jhi, KeyRange{lo,hi_})
debugfRSet("\tmerge S[%d:%d]\t-> %s\n", ilo, jhi, S)
}
jhi = -1 // no longer valid
// if [r.lo,r.hi) was outside of any entry - create new entry
if r.hi_ < S.rangev[ilo].lo {
S.rangev = append(
S.rangev[:ilo], append([]KeyRange{
r},
S.rangev[ilo:]...)...)
vInsert(&S.rangev, ilo, r)
debugfRSet("\tinsert %s\t-> %s\n", r, S)
}
......@@ -140,20 +134,16 @@ func (S *RangedKeySet) AddRange(r KeyRange) {
// and check if we should merge it with right/left neighbours
if ilo+1 < len(S.rangev) { // right
if S.rangev[ilo].hi_+1 == S.rangev[ilo+1].lo {
S.rangev = append(
S.rangev[:ilo], append([]KeyRange{
KeyRange{S.rangev[ilo].lo, S.rangev[ilo+1].hi_}},
S.rangev[ilo+2:]...)...)
vReplaceSlice(&S.rangev, ilo,ilo+2,
KeyRange{S.rangev[ilo].lo, S.rangev[ilo+1].hi_})
debugfRSet("\tmerge right\t-> %s\n", S)
}
}
if ilo > 0 { // left
if S.rangev[ilo-1].hi_+1 == S.rangev[ilo].lo {
S.rangev = append(
S.rangev[:ilo-1], append([]KeyRange{
KeyRange{S.rangev[ilo-1].lo, S.rangev[ilo].hi_}},
S.rangev[ilo+1:]...)...)
vReplaceSlice(&S.rangev, ilo-1,ilo+1,
KeyRange{S.rangev[ilo-1].lo, S.rangev[ilo].hi_})
debugfRSet("\tmerge left\t-> %s\n", S)
}
}
......@@ -204,38 +194,27 @@ func (S *RangedKeySet) DelRange(r KeyRange) {
}
// [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]
if jhi-ilo == 1 && S.rangev[ilo].lo < r.lo && r.hi_ < S.rangev[ilo].hi_ {
x := S.rangev[ilo]
S.rangev = append(
S.rangev[:ilo], append([]KeyRange{
x, x},
S.rangev[ilo+1:]...)...)
vInsert(&S.rangev, ilo, x)
jhi++
debugfRSet("\tpresplit copy %s\t-> %s\n", x, S)
}
if S.rangev[ilo].lo < r.lo { // shrink left
S.rangev = append(
S.rangev[:ilo], append([]KeyRange{
KeyRange{S.rangev[ilo].lo, r.lo-1}},
S.rangev[ilo+1:]...)...)
S.rangev[ilo] = KeyRange{S.rangev[ilo].lo, r.lo-1}
ilo++
debugfRSet("\tshrink [%d] left\t-> %s\n", ilo, S)
}
if r.hi_ < S.rangev[jhi-1].hi_ { // shrink right
S.rangev = append(
S.rangev[:jhi-1], append([]KeyRange{
KeyRange{r.hi_+1, S.rangev[jhi-1].hi_}},
S.rangev[jhi:]...)...)
S.rangev[jhi-1] = KeyRange{r.hi_+1, S.rangev[jhi-1].hi_}
jhi--
debugfRSet("\tshrink [%d] right\t-> %s\n", jhi-1, S)
}
if (jhi - ilo) > 0 {
S.rangev = append(
S.rangev[:ilo],
S.rangev[jhi:]...)
vDeleteSlice(&S.rangev, ilo,jhi)
debugfRSet("\tdelete S[%d:%d]\t-> %s\n", ilo, jhi, S)
}
......@@ -414,3 +393,32 @@ func debugfRSet(format string, argv ...interface{}) {
}
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