Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
b
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
b
Commits
5aafa674
Commit
5aafa674
authored
Jun 26, 2014
by
Jan Mercl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lower GC presure by recycling things.
parent
d2d7ab5c
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
287 additions
and
148 deletions
+287
-148
Makefile
Makefile
+17
-7
all_test.go
all_test.go
+23
-7
btree.go
btree.go
+108
-44
example/Makefile
example/Makefile
+8
-1
example/all_test.go
example/all_test.go
+27
-47
example/int.go
example/int.go
+104
-42
No files found.
Makefile
View file @
5aafa674
.PHONY
:
all todo clean cover generic
.PHONY
:
all todo clean cover generic mem nuke
testbin
=
b.test
all
:
editor
go build
...
...
@@ -11,12 +13,6 @@ editor:
go
test
-i
go
test
todo
:
@
grep
-n
^[[:space:]]
*
_[[:space:]]
*
=[[
:space:]][[:alpha:]][[:alnum:]]
*
*
.go
||
true
@
grep
-n
TODO
*
.go
||
true
@
grep
-n
BUG
*
.go
||
true
@
grep
-n
println
*
.go
||
true
clean
:
@
go clean
rm
-f
*
~
...
...
@@ -31,3 +27,17 @@ generic:
@
# Intended use is to replace all textual occurrences of KEY or VALUE in
@
# the output with your desired types.
@
sed
-e
's|interface{}[^{]*/\*K\*/|KEY|g'
-e
's|interface{}[^{]*/\*V\*/|VALUE|g'
btree.go
mem
:
go
test
-c
./
$(testbin)
-test
.bench
.
-test
.memprofile mem.out
-test
.memprofilerate 1
go tool pprof
--lines
--web
--alloc_space
$(testbin)
mem.out
nuke
:
clean
rm
-f
*
.test
*
.out
todo
:
@
grep
-n
^[[:space:]]
*
_[[:space:]]
*
=[[
:space:]][[:alpha:]][[:alnum:]]
*
*
.go
||
true
@
grep
-n
TODO
*
.go
||
true
@
grep
-n
BUG
*
.go
||
true
@
grep
-n
println
*
.go
||
true
all_test.go
View file @
5aafa674
// Copyright 201
3
The Go Authors. All rights reserved.
// Copyright 201
4
The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
...
...
@@ -279,6 +279,8 @@ func benchmarkSetSeq(b *testing.B, n int) {
for
j
:=
0
;
j
<
n
;
j
++
{
r
.
Set
(
j
,
j
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
...
...
@@ -312,6 +314,7 @@ func benchmarkGetSeq(b *testing.B, n int) {
}
}
b
.
StopTimer
()
r
.
Close
()
}
func
BenchmarkSetRnd1e3
(
b
*
testing
.
B
)
{
...
...
@@ -345,6 +348,8 @@ func benchmarkSetRnd(b *testing.B, n int) {
for
_
,
v
:=
range
a
{
r
.
Set
(
v
,
0
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
...
...
@@ -383,6 +388,7 @@ func benchmarkGetRnd(b *testing.B, n int) {
}
}
b
.
StopTimer
()
r
.
Close
()
}
func
TestSetGet2
(
t
*
testing
.
T
)
{
...
...
@@ -557,19 +563,19 @@ func TestDelete1(t *testing.T) {
}
}
func
b
enchmarkDelSeq1e3
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e3
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e3
)
}
func
b
enchmarkDelSeq1e4
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e4
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e4
)
}
func
b
enchmarkDelSeq1e5
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e5
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e5
)
}
func
b
enchmarkDelSeq1e6
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e6
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e6
)
}
...
...
@@ -624,6 +630,8 @@ func benchmarkDelRnd(b *testing.B, n int) {
for
_
,
v
:=
range
a
{
r
.
Delete
(
v
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
...
...
@@ -821,8 +829,11 @@ func benchmarkSeekSeq(b *testing.B, n int) {
debug
.
FreeOSMemory
()
b
.
StartTimer
()
for
j
:=
0
;
j
<
n
;
j
++
{
t
.
Seek
(
j
)
e
,
_
:=
t
.
Seek
(
j
)
e
.
Close
()
}
b
.
StopTimer
()
t
.
Close
()
}
b
.
StopTimer
()
}
...
...
@@ -857,9 +868,12 @@ func benchmarkSeekRnd(b *testing.B, n int) {
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
_
,
v
:=
range
a
{
r
.
Seek
(
v
)
e
,
_
:=
r
.
Seek
(
v
)
e
.
Close
()
}
}
b
.
StopTimer
()
r
.
Close
()
}
func
BenchmarkNext1e3
(
b
*
testing
.
B
)
{
...
...
@@ -902,6 +916,8 @@ func benchmarkNext(b *testing.B, n int) {
b
.
Fatal
(
m
)
}
}
b
.
StopTimer
()
t
.
Close
()
}
func
BenchmarkPrev1e3
(
b
*
testing
.
B
)
{
...
...
btree.go
View file @
5aafa674
This diff is collapsed.
Click to expand it.
example/Makefile
View file @
5aafa674
.PHONY
:
all todo clean cover
.PHONY
:
all todo clean cover mem
testbin
=
b.test
all
:
editor
go build
...
...
@@ -10,6 +12,11 @@ editor:
go
test
-i
go
test
mem
:
go
test
-c
./
$(testbin)
-test
.bench
.
-test
.memprofile mem.out
-test
.memprofilerate 1
go tool pprof
--lines
--web
--alloc_space
$(testbin)
mem.out
todo
:
@
grep
-n
^[[:space:]]
*
_[[:space:]]
*
=[[
:space:]][[:alpha:]][[:alnum:]]
*
*
.go
||
true
@
grep
-n
TODO
*
.go
||
true
...
...
example/all_test.go
View file @
5aafa674
// Copyright 201
3
The Go Authors. All rights reserved.
// Copyright 201
4
The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
...
...
@@ -131,10 +131,6 @@ func TestSetGet1(t *testing.T) {
}
}
func
BenchmarkSetSeq1e2
(
b
*
testing
.
B
)
{
benchmarkSetSeq
(
b
,
1e2
)
}
func
BenchmarkSetSeq1e3
(
b
*
testing
.
B
)
{
benchmarkSetSeq
(
b
,
1e3
)
}
...
...
@@ -161,14 +157,12 @@ func benchmarkSetSeq(b *testing.B, n int) {
for
j
:=
0
;
j
<
n
;
j
++
{
r
.
Set
(
j
,
j
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
func
BenchmarkGetSeq1e2
(
b
*
testing
.
B
)
{
benchmarkGetSeq
(
b
,
1e2
)
}
func
BenchmarkGetSeq1e3
(
b
*
testing
.
B
)
{
benchmarkGetSeq
(
b
,
1e3
)
}
...
...
@@ -198,10 +192,7 @@ func benchmarkGetSeq(b *testing.B, n int) {
}
}
b
.
StopTimer
()
}
func
BenchmarkSetRnd1e2
(
b
*
testing
.
B
)
{
benchmarkSetRnd
(
b
,
1e2
)
r
.
Close
()
}
func
BenchmarkSetRnd1e3
(
b
*
testing
.
B
)
{
...
...
@@ -235,14 +226,12 @@ func benchmarkSetRnd(b *testing.B, n int) {
for
_
,
v
:=
range
a
{
r
.
Set
(
v
,
0
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
func
BenchmarkGetRnd1e2
(
b
*
testing
.
B
)
{
benchmarkGetRnd
(
b
,
1e2
)
}
func
BenchmarkGetRnd1e3
(
b
*
testing
.
B
)
{
benchmarkGetRnd
(
b
,
1e3
)
}
...
...
@@ -277,6 +266,7 @@ func benchmarkGetRnd(b *testing.B, n int) {
}
}
b
.
StopTimer
()
r
.
Close
()
}
func
TestSetGet2
(
t
*
testing
.
T
)
{
...
...
@@ -451,23 +441,19 @@ func TestDelete1(t *testing.T) {
}
}
func
benchmarkDelSeq1e2
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e2
)
}
func
benchmarkDelSeq1e3
(
b
*
testing
.
B
)
{
func
BenchmarkDelSeq1e3
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e3
)
}
func
b
enchmarkDelSeq1e4
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e4
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e4
)
}
func
b
enchmarkDelSeq1e5
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e5
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e5
)
}
func
b
enchmarkDelSeq1e6
(
b
*
testing
.
B
)
{
func
B
enchmarkDelSeq1e6
(
b
*
testing
.
B
)
{
benchmarkDelSeq
(
b
,
1e6
)
}
...
...
@@ -484,14 +470,12 @@ func benchmarkDelSeq(b *testing.B, n int) {
for
j
:=
0
;
j
<
n
;
j
++
{
r
.
Delete
(
j
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
func
BenchmarkDelRnd1e2
(
b
*
testing
.
B
)
{
benchmarkDelRnd
(
b
,
1e2
)
}
func
BenchmarkDelRnd1e3
(
b
*
testing
.
B
)
{
benchmarkDelRnd
(
b
,
1e3
)
}
...
...
@@ -526,6 +510,8 @@ func benchmarkDelRnd(b *testing.B, n int) {
for
_
,
v
:=
range
a
{
r
.
Delete
(
v
)
}
b
.
StopTimer
()
r
.
Close
()
}
b
.
StopTimer
()
}
...
...
@@ -697,10 +683,6 @@ func TestEnumeratorPrev(t *testing.T) {
}
}
func
BenchmarkSeekSeq1e2
(
b
*
testing
.
B
)
{
benchmarkSeekSeq
(
b
,
1e2
)
}
func
BenchmarkSeekSeq1e3
(
b
*
testing
.
B
)
{
benchmarkSeekSeq
(
b
,
1e3
)
}
...
...
@@ -727,16 +709,15 @@ func benchmarkSeekSeq(b *testing.B, n int) {
debug
.
FreeOSMemory
()
b
.
StartTimer
()
for
j
:=
0
;
j
<
n
;
j
++
{
t
.
Seek
(
j
)
e
,
_
:=
t
.
Seek
(
j
)
e
.
Close
()
}
b
.
StopTimer
()
t
.
Close
()
}
b
.
StopTimer
()
}
func
BenchmarkSeekRnd1e2
(
b
*
testing
.
B
)
{
benchmarkSeekRnd
(
b
,
1e2
)
}
func
BenchmarkSeekRnd1e3
(
b
*
testing
.
B
)
{
benchmarkSeekRnd
(
b
,
1e3
)
}
...
...
@@ -767,13 +748,12 @@ func benchmarkSeekRnd(b *testing.B, n int) {
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
_
,
v
:=
range
a
{
r
.
Seek
(
v
)
e
,
_
:=
r
.
Seek
(
v
)
e
.
Close
()
}
}
}
func
BenchmarkNext1e2
(
b
*
testing
.
B
)
{
benchmarkNext
(
b
,
1e2
)
b
.
StopTimer
()
r
.
Close
()
}
func
BenchmarkNext1e3
(
b
*
testing
.
B
)
{
...
...
@@ -816,10 +796,8 @@ func benchmarkNext(b *testing.B, n int) {
b
.
Fatal
(
m
)
}
}
}
func
BenchmarkPrev1e2
(
b
*
testing
.
B
)
{
benchmarkPrev
(
b
,
1e2
)
b
.
StopTimer
()
t
.
Close
()
}
func
BenchmarkPrev1e3
(
b
*
testing
.
B
)
{
...
...
@@ -862,6 +840,8 @@ func benchmarkPrev(b *testing.B, n int) {
b
.
Fatal
(
m
)
}
}
b
.
StopTimer
()
t
.
Close
()
}
func
TestSeekFirst0
(
t
*
testing
.
T
)
{
...
...
example/int.go
View file @
5aafa674
// Copyright 201
3
The Go Authors. All rights reserved.
// Copyright 201
4
The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
...
...
@@ -8,10 +8,9 @@ package b
import
(
"fmt"
"io"
"sync"
)
//TODO check vs orig initialize/finalize
const
(
kx
=
32
//TODO benchmark tune this number if using custom key/value type(s).
kd
=
32
//TODO benchmark tune this number if using custom key/value type(s).
...
...
@@ -27,6 +26,29 @@ func init() {
}
}
var
(
btDPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
d
{}
}}
btEPool
=
btEpool
{
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
Enumerator
{}
}}}
btTPool
=
btTpool
{
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
Tree
{}
}}}
btXPool
=
sync
.
Pool
{
New
:
func
()
interface
{}
{
return
&
x
{}
}}
)
type
btTpool
struct
{
sync
.
Pool
}
func
(
p
*
btTpool
)
get
(
cmp
Cmp
)
*
Tree
{
x
:=
p
.
Get
()
.
(
*
Tree
)
x
.
cmp
=
cmp
return
x
}
type
btEpool
struct
{
sync
.
Pool
}
func
(
p
*
btEpool
)
get
(
err
error
,
hit
bool
,
i
int
,
k
int
,
q
*
d
,
t
*
Tree
,
ver
int64
)
*
Enumerator
{
x
:=
p
.
Get
()
.
(
*
Enumerator
)
x
.
err
,
x
.
hit
,
x
.
i
,
x
.
k
,
x
.
q
,
x
.
t
,
x
.
ver
=
err
,
hit
,
i
,
k
,
q
,
t
,
ver
return
x
}
type
(
// Cmp compares a and b. Return value is:
//
...
...
@@ -90,9 +112,11 @@ type (
var
(
// R/O zero values
zd
d
zde
de
ze
Enumerator
zk
int
zt
Tree
zx
x
zxe
xe
zk
int
)
func
clr
(
q
interface
{})
{
...
...
@@ -101,16 +125,18 @@ func clr(q interface{}) {
for
i
:=
0
;
i
<=
x
.
c
;
i
++
{
// Ch0 Sep0 ... Chn-1 Sepn-1 Chn
clr
(
x
.
x
[
i
]
.
ch
)
}
*
x
=
zx
// GC
*
x
=
zx
btXPool
.
Put
(
x
)
case
*
d
:
*
x
=
zd
// GC
*
x
=
zd
btDPool
.
Put
(
x
)
}
}
// -------------------------------------------------------------------------- x
func
newX
(
ch0
interface
{})
*
x
{
r
:=
&
x
{}
r
:=
btXPool
.
Get
()
.
(
*
x
)
r
.
x
[
0
]
.
ch
=
ch0
return
r
}
...
...
@@ -172,7 +198,7 @@ func (l *d) mvR(r *d, c int) {
// TreeNew returns a newly created, empty Tree. The compare function is used
// for key collation.
func
TreeNew
(
cmp
Cmp
)
*
Tree
{
return
&
Tree
{
cmp
:
cmp
}
return
btTPool
.
get
(
cmp
)
}
// Clear removes all K/V pairs from the tree.
...
...
@@ -186,6 +212,14 @@ func (t *Tree) Clear() {
t
.
ver
++
}
// Close performs Clear and recycles t to a pool for possible later reuse. No
// references to t should exist or such references must not be used afterwards.
func
(
t
*
Tree
)
Close
()
{
t
.
Clear
()
*
t
=
zt
btTPool
.
Put
(
t
)
}
func
(
t
*
Tree
)
cat
(
p
*
x
,
q
,
r
*
d
,
pi
int
)
{
t
.
ver
++
q
.
mvL
(
r
,
r
.
c
)
...
...
@@ -194,11 +228,21 @@ func (t *Tree) cat(p *x, q, r *d, pi int) {
}
else
{
t
.
last
=
q
}
q
.
n
=
r
.
n
//TODO recycle r
q
.
n
=
r
.
n
*
r
=
zd
btDPool
.
Put
(
r
)
if
p
.
c
>
1
{
p
.
extract
(
pi
)
p
.
x
[
pi
]
.
ch
=
q
}
else
{
//TODO recycle r
}
else
{
switch
x
:=
t
.
r
.
(
type
)
{
case
*
x
:
*
x
=
zx
btXPool
.
Put
(
x
)
case
*
d
:
*
x
=
zd
btDPool
.
Put
(
x
)
}
t
.
r
=
q
}
}
...
...
@@ -208,7 +252,9 @@ func (t *Tree) catX(p, q, r *x, pi int) {
q
.
x
[
q
.
c
]
.
k
=
p
.
x
[
pi
]
.
k
copy
(
q
.
x
[
q
.
c
+
1
:
],
r
.
x
[
:
r
.
c
])
q
.
c
+=
r
.
c
+
1
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
r
.
c
]
.
ch
//TODO recycle r
q
.
x
[
q
.
c
]
.
ch
=
r
.
x
[
r
.
c
]
.
ch
*
r
=
zx
btXPool
.
Put
(
r
)
if
p
.
c
>
1
{
p
.
c
--
pc
:=
p
.
c
...
...
@@ -222,7 +268,15 @@ func (t *Tree) catX(p, q, r *x, pi int) {
return
}
t
.
r
=
q
//TODO recycle r
switch
x
:=
t
.
r
.
(
type
)
{
case
*
x
:
*
x
=
zx
btXPool
.
Put
(
x
)
case
*
d
:
*
x
=
zd
btDPool
.
Put
(
x
)
}
t
.
r
=
q
}
// Delete removes the k's KV pair, if it exists, in which case Delete returns
...
...
@@ -242,7 +296,7 @@ func (t *Tree) Delete(k int) (ok bool) {
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
t
.
underflowX
(
p
,
&
x
,
pi
,
&
i
)
x
,
i
=
t
.
underflowX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
p
=
x
...
...
@@ -267,7 +321,7 @@ func (t *Tree) Delete(k int) (ok bool) {
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
<
kx
&&
q
!=
t
.
r
{
t
.
underflowX
(
p
,
&
x
,
pi
,
&
i
)
x
,
i
=
t
.
underflowX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
p
=
x
...
...
@@ -424,7 +478,7 @@ func (t *Tree) overflow(p *x, q *d, pi, i int, k int, v int) {
func
(
t
*
Tree
)
Seek
(
k
int
)
(
e
*
Enumerator
,
ok
bool
)
{
q
:=
t
.
r
if
q
==
nil
{
e
=
&
Enumerator
{
nil
,
false
,
0
,
k
,
nil
,
t
,
t
.
ver
}
e
=
btEPool
.
get
(
nil
,
false
,
0
,
k
,
nil
,
t
,
t
.
ver
)
return
}
...
...
@@ -436,16 +490,15 @@ func (t *Tree) Seek(k int) (e *Enumerator, ok bool) {
q
=
x
.
x
[
i
+
1
]
.
ch
continue
case
*
d
:
e
=
&
Enumerator
{
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
}
return
return
btEPool
.
get
(
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
),
true
}
}
switch
x
:=
q
.
(
type
)
{
case
*
x
:
q
=
x
.
x
[
i
]
.
ch
case
*
d
:
e
=
&
Enumerator
{
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
}
return
return
btEPool
.
get
(
nil
,
ok
,
i
,
k
,
x
,
t
,
t
.
ver
),
false
}
}
}
...
...
@@ -458,7 +511,7 @@ func (t *Tree) SeekFirst() (e *Enumerator, err error) {
return
nil
,
io
.
EOF
}
return
&
Enumerator
{
nil
,
true
,
0
,
q
.
d
[
0
]
.
k
,
q
,
t
,
t
.
ver
}
,
nil
return
btEPool
.
get
(
nil
,
true
,
0
,
q
.
d
[
0
]
.
k
,
q
,
t
,
t
.
ver
)
,
nil
}
// SeekLast returns an enumerator positioned on the last KV pair in the tree,
...
...
@@ -469,7 +522,7 @@ func (t *Tree) SeekLast() (e *Enumerator, err error) {
return
nil
,
io
.
EOF
}
return
&
Enumerator
{
nil
,
true
,
q
.
c
-
1
,
q
.
d
[
q
.
c
-
1
]
.
k
,
q
,
t
,
t
.
ver
}
,
nil
return
btEPool
.
get
(
nil
,
true
,
q
.
c
-
1
,
q
.
d
[
q
.
c
-
1
]
.
k
,
q
,
t
,
t
.
ver
)
,
nil
}
// Set sets the value associated with k.
...
...
@@ -482,7 +535,7 @@ func (t *Tree) Set(k int, v int) {
var
p
*
x
q
:=
t
.
r
if
q
==
nil
{
z
:=
t
.
insert
(
&
d
{}
,
0
,
k
,
v
)
z
:=
t
.
insert
(
btDPool
.
Get
()
.
(
*
d
)
,
0
,
k
,
v
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
return
}
...
...
@@ -493,7 +546,7 @@ func (t *Tree) Set(k int, v int) {
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
t
.
splitX
(
p
,
&
x
,
pi
,
&
i
)
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
p
=
x
...
...
@@ -508,7 +561,7 @@ func (t *Tree) Set(k int, v int) {
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
t
.
splitX
(
p
,
&
x
,
pi
,
&
i
)
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
p
=
x
...
...
@@ -549,7 +602,7 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
t
.
splitX
(
p
,
&
x
,
pi
,
&
i
)
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
+
1
p
=
x
...
...
@@ -570,7 +623,7 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
switch
x
:=
q
.
(
type
)
{
case
*
x
:
if
x
.
c
>
2
*
kx
{
t
.
splitX
(
p
,
&
x
,
pi
,
&
i
)
x
,
i
=
t
.
splitX
(
p
,
x
,
pi
,
i
)
}
pi
=
i
p
=
x
...
...
@@ -598,14 +651,14 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
return
}
z
:=
t
.
insert
(
&
d
{}
,
0
,
k
,
newV
)
z
:=
t
.
insert
(
btDPool
.
Get
()
.
(
*
d
)
,
0
,
k
,
newV
)
t
.
r
,
t
.
first
,
t
.
last
=
z
,
z
,
z
return
}
func
(
t
*
Tree
)
split
(
p
*
x
,
q
*
d
,
pi
,
i
int
,
k
int
,
v
int
)
{
t
.
ver
++
r
:=
&
d
{}
r
:=
btDPool
.
Get
()
.
(
*
d
)
if
q
.
n
!=
nil
{
r
.
n
=
q
.
n
r
.
n
.
p
=
r
...
...
@@ -638,10 +691,9 @@ func (t *Tree) split(p *x, q *d, pi, i int, k int, v int) {
t
.
insert
(
q
,
i
,
k
,
v
)
}
func
(
t
*
Tree
)
splitX
(
p
*
x
,
pp
**
x
,
pi
int
,
i
*
int
)
{
func
(
t
*
Tree
)
splitX
(
p
*
x
,
q
*
x
,
pi
int
,
i
int
)
(
*
x
,
int
)
{
t
.
ver
++
q
:=
*
pp
r
:=
&
x
{}
r
:=
btXPool
.
Get
()
.
(
*
x
)
copy
(
r
.
x
[
:
],
q
.
x
[
kx
+
1
:
])
q
.
c
=
kx
r
.
c
=
kx
...
...
@@ -654,10 +706,11 @@ func (t *Tree) splitX(p *x, pp **x, pi int, i *int) {
for
i
:=
range
q
.
x
[
kx
+
1
:
]
{
q
.
x
[
kx
+
i
+
1
]
=
zxe
}
if
*
i
>
kx
{
*
pp
=
r
*
i
-=
kx
+
1
if
i
>
kx
{
q
=
r
i
-=
kx
+
1
}
return
q
,
i
}
func
(
t
*
Tree
)
underflow
(
p
*
x
,
q
*
d
,
pi
int
)
{
...
...
@@ -678,10 +731,9 @@ func (t *Tree) underflow(p *x, q *d, pi int) {
}
}
func
(
t
*
Tree
)
underflowX
(
p
*
x
,
pp
**
x
,
pi
int
,
i
*
int
)
{
func
(
t
*
Tree
)
underflowX
(
p
*
x
,
q
*
x
,
pi
int
,
i
int
)
(
*
x
,
int
)
{
t
.
ver
++
var
l
,
r
*
x
q
:=
*
pp
if
pi
>=
0
{
if
pi
>
0
{
...
...
@@ -698,10 +750,10 @@ func (t *Tree) underflowX(p *x, pp **x, pi int, i *int) {
q
.
x
[
0
]
.
ch
=
l
.
x
[
l
.
c
]
.
ch
q
.
x
[
0
]
.
k
=
p
.
x
[
pi
-
1
]
.
k
q
.
c
++
*
i
++
i
++
l
.
c
--
p
.
x
[
pi
-
1
]
.
k
=
l
.
x
[
l
.
c
]
.
k
return
return
q
,
i
}
if
r
!=
nil
&&
r
.
c
>
kx
{
...
...
@@ -715,21 +767,29 @@ func (t *Tree) underflowX(p *x, pp **x, pi int, i *int) {
r
.
x
[
rc
]
.
ch
=
r
.
x
[
rc
+
1
]
.
ch
r
.
x
[
rc
]
.
k
=
zk
r
.
x
[
rc
+
1
]
.
ch
=
nil
return
return
q
,
i
}
if
l
!=
nil
{
*
i
+=
l
.
c
+
1
i
+=
l
.
c
+
1
t
.
catX
(
p
,
l
,
q
,
pi
-
1
)
*
pp
=
l
return
q
=
l
return
q
,
i
}
t
.
catX
(
p
,
q
,
r
,
pi
)
return
q
,
i
}
// ----------------------------------------------------------------- Enumerator
// Close recycles e to a pool for possible later reuse. No references to e
// should exist or such references must not be used afterwards.
func
(
e
*
Enumerator
)
Close
()
{
*
e
=
ze
btEPool
.
Put
(
e
)
}
// Next returns the currently enumerated item, if it exists and moves to the
// next item in the key collation order. If there is no item to return, err ==
// io.EOF is returned.
...
...
@@ -747,6 +807,7 @@ func (e *Enumerator) Next() (k int, v int, err error) {
}
*
e
=
*
f
f
.
Close
()
}
if
e
.
q
==
nil
{
e
.
err
,
err
=
io
.
EOF
,
io
.
EOF
...
...
@@ -800,6 +861,7 @@ func (e *Enumerator) Prev() (k int, v int, err error) {
}
*
e
=
*
f
f
.
Close
()
}
if
e
.
q
==
nil
{
e
.
err
,
err
=
io
.
EOF
,
io
.
EOF
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment