Use cznic/b for index store
$ benchcmp gollrb.bench b-gen.bench
benchmark old ns/op new ns/op delta
BenchmarkNamePredicate 1731218 1693373 -2.19%
BenchmarkLargeSetsNoIntersection 81290360 70205277 -13.64%
BenchmarkVeryLargeSetsSmallIntersection 768135620 442906243 -42.34%
BenchmarkHelplessContainsChecker 39477086024 35260603748 -10.68%
BenchmarkNetAndSpeed 22510637 21587975 -4.10%
BenchmarkKeanuAndNet 18018886 17795328 -1.24%
BenchmarkKeanuAndSpeed 20336586 20560228 +1.10%
BenchmarkKeanuOther 85495040 80718152 -5.59%
BenchmarkKeanuBullockOther 95457792 83868434 -12.14%
Code gen from $GOPATH/src/github.com/cznic/b:
make generic \
| sed -e 's/KEY/int64/g' -e 's/VALUE/struct{}/g' \
> $GOPATH/src/github.com/google/cayley/graph/memstore/b/keys.go
key_test.go manually edited.
This commit is contained in:
parent
aad21b0585
commit
2540ea8f87
4 changed files with 1492 additions and 114 deletions
|
|
@ -18,11 +18,11 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/barakmich/glog"
|
||||
|
||||
"github.com/google/cayley/graph"
|
||||
"github.com/google/cayley/graph/iterator"
|
||||
"github.com/google/cayley/graph/memstore/b"
|
||||
"github.com/google/cayley/quad"
|
||||
|
||||
"github.com/petar/GoLLRB/llrb"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
@ -32,47 +32,36 @@ func init() {
|
|||
}
|
||||
|
||||
type TripleDirectionIndex struct {
|
||||
subject map[int64]*llrb.LLRB
|
||||
predicate map[int64]*llrb.LLRB
|
||||
object map[int64]*llrb.LLRB
|
||||
label map[int64]*llrb.LLRB
|
||||
index [4]map[int64]*b.Tree
|
||||
}
|
||||
|
||||
func NewTripleDirectionIndex() *TripleDirectionIndex {
|
||||
var tdi TripleDirectionIndex
|
||||
tdi.subject = make(map[int64]*llrb.LLRB)
|
||||
tdi.predicate = make(map[int64]*llrb.LLRB)
|
||||
tdi.object = make(map[int64]*llrb.LLRB)
|
||||
tdi.label = make(map[int64]*llrb.LLRB)
|
||||
return &tdi
|
||||
func NewTripleDirectionIndex() TripleDirectionIndex {
|
||||
return TripleDirectionIndex{[...]map[int64]*b.Tree{
|
||||
quad.Subject - 1: make(map[int64]*b.Tree),
|
||||
quad.Predicate - 1: make(map[int64]*b.Tree),
|
||||
quad.Object - 1: make(map[int64]*b.Tree),
|
||||
quad.Label - 1: make(map[int64]*b.Tree),
|
||||
}}
|
||||
}
|
||||
|
||||
func (tdi *TripleDirectionIndex) GetForDir(d quad.Direction) map[int64]*llrb.LLRB {
|
||||
switch d {
|
||||
case quad.Subject:
|
||||
return tdi.subject
|
||||
case quad.Object:
|
||||
return tdi.object
|
||||
case quad.Predicate:
|
||||
return tdi.predicate
|
||||
case quad.Label:
|
||||
return tdi.label
|
||||
func (tdi TripleDirectionIndex) Tree(d quad.Direction, id int64) *b.Tree {
|
||||
if d < quad.Subject || d > quad.Label {
|
||||
panic("illegal direction")
|
||||
}
|
||||
panic("illegal direction")
|
||||
}
|
||||
|
||||
func (tdi *TripleDirectionIndex) GetOrCreate(d quad.Direction, id int64) *llrb.LLRB {
|
||||
directionIndex := tdi.GetForDir(d)
|
||||
if _, ok := directionIndex[id]; !ok {
|
||||
directionIndex[id] = llrb.New()
|
||||
tree, ok := tdi.index[d-1][id]
|
||||
if !ok {
|
||||
tree = b.TreeNew(cmp)
|
||||
tdi.index[d-1][id] = tree
|
||||
}
|
||||
return directionIndex[id]
|
||||
return tree
|
||||
}
|
||||
|
||||
func (tdi *TripleDirectionIndex) Get(d quad.Direction, id int64) (*llrb.LLRB, bool) {
|
||||
directionIndex := tdi.GetForDir(d)
|
||||
tree, exists := directionIndex[id]
|
||||
return tree, exists
|
||||
func (tdi TripleDirectionIndex) Get(d quad.Direction, id int64) (*b.Tree, bool) {
|
||||
if d < quad.Subject || d > quad.Label {
|
||||
panic("illegal direction")
|
||||
}
|
||||
tree, ok := tdi.index[d-1][id]
|
||||
return tree, ok
|
||||
}
|
||||
|
||||
type TripleStore struct {
|
||||
|
|
@ -83,22 +72,22 @@ type TripleStore struct {
|
|||
triples []quad.Quad
|
||||
size int64
|
||||
index TripleDirectionIndex
|
||||
// vip_index map[string]map[int64]map[string]map[int64]*llrb.Tree
|
||||
// vip_index map[string]map[int64]map[string]map[int64]*b.Tree
|
||||
}
|
||||
|
||||
func newTripleStore() *TripleStore {
|
||||
var ts TripleStore
|
||||
ts.idMap = make(map[string]int64)
|
||||
ts.revIdMap = make(map[int64]string)
|
||||
ts.triples = make([]quad.Quad, 1, 200)
|
||||
return &TripleStore{
|
||||
idMap: make(map[string]int64),
|
||||
revIdMap: make(map[int64]string),
|
||||
|
||||
// Sentinel null triple so triple indices start at 1
|
||||
ts.triples[0] = quad.Quad{}
|
||||
ts.size = 1
|
||||
ts.index = *NewTripleDirectionIndex()
|
||||
ts.idCounter = 1
|
||||
ts.tripleIdCounter = 1
|
||||
return &ts
|
||||
// Sentinel null triple so triple indices start at 1
|
||||
triples: make([]quad.Quad, 1, 200),
|
||||
|
||||
size: 1,
|
||||
index: NewTripleDirectionIndex(),
|
||||
idCounter: 1,
|
||||
tripleIdCounter: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TripleStore) AddTripleSet(triples []quad.Quad) {
|
||||
|
|
@ -107,47 +96,47 @@ func (ts *TripleStore) AddTripleSet(triples []quad.Quad) {
|
|||
}
|
||||
}
|
||||
|
||||
func (ts *TripleStore) tripleExists(t quad.Quad) (bool, int64) {
|
||||
smallest := -1
|
||||
var smallest_tree *llrb.LLRB
|
||||
const maxInt = int(^uint(0) >> 1)
|
||||
|
||||
func (ts *TripleStore) indexOf(t quad.Quad) (int64, bool) {
|
||||
min := maxInt
|
||||
var tree *b.Tree
|
||||
for d := quad.Subject; d <= quad.Label; d++ {
|
||||
sid := t.Get(d)
|
||||
if d == quad.Label && sid == "" {
|
||||
continue
|
||||
}
|
||||
id, ok := ts.idMap[sid]
|
||||
// If we've never heard about a node, it most not exist
|
||||
// If we've never heard about a node, it must not exist
|
||||
if !ok {
|
||||
return false, 0
|
||||
return 0, false
|
||||
}
|
||||
index, exists := ts.index.Get(d, id)
|
||||
if !exists {
|
||||
index, ok := ts.index.Get(d, id)
|
||||
if !ok {
|
||||
// If it's never been indexed in this direction, it can't exist.
|
||||
return false, 0
|
||||
return 0, false
|
||||
}
|
||||
if smallest == -1 || index.Len() < smallest {
|
||||
smallest = index.Len()
|
||||
smallest_tree = index
|
||||
if l := index.Len(); l < min {
|
||||
min, tree = l, index
|
||||
}
|
||||
}
|
||||
it := NewLlrbIterator(smallest_tree, "")
|
||||
it := NewIterator(tree, "")
|
||||
|
||||
for it.Next() {
|
||||
val := it.Result()
|
||||
if t == ts.triples[val.(int64)] {
|
||||
return true, val.(int64)
|
||||
return val.(int64), true
|
||||
}
|
||||
}
|
||||
return false, 0
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (ts *TripleStore) AddTriple(t quad.Quad) {
|
||||
if exists, _ := ts.tripleExists(t); exists {
|
||||
if _, exists := ts.indexOf(t); exists {
|
||||
return
|
||||
}
|
||||
var tripleID int64
|
||||
ts.triples = append(ts.triples, t)
|
||||
tripleID = ts.tripleIdCounter
|
||||
tid := ts.tripleIdCounter
|
||||
ts.size++
|
||||
ts.tripleIdCounter++
|
||||
|
||||
|
|
@ -168,22 +157,20 @@ func (ts *TripleStore) AddTriple(t quad.Quad) {
|
|||
continue
|
||||
}
|
||||
id := ts.idMap[t.Get(d)]
|
||||
tree := ts.index.GetOrCreate(d, id)
|
||||
tree.ReplaceOrInsert(Int64(tripleID))
|
||||
tree := ts.index.Tree(d, id)
|
||||
tree.Set(tid, struct{}{})
|
||||
}
|
||||
|
||||
// TODO(barakmich): Add VIP indexing
|
||||
}
|
||||
|
||||
func (ts *TripleStore) RemoveTriple(t quad.Quad) {
|
||||
var tripleID int64
|
||||
var exists bool
|
||||
tripleID = 0
|
||||
if exists, tripleID = ts.tripleExists(t); !exists {
|
||||
tid, ok := ts.indexOf(t)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
ts.triples[tripleID] = quad.Quad{}
|
||||
ts.triples[tid] = quad.Quad{}
|
||||
ts.size--
|
||||
|
||||
for d := quad.Subject; d <= quad.Label; d++ {
|
||||
|
|
@ -191,8 +178,8 @@ func (ts *TripleStore) RemoveTriple(t quad.Quad) {
|
|||
continue
|
||||
}
|
||||
id := ts.idMap[t.Get(d)]
|
||||
tree := ts.index.GetOrCreate(d, id)
|
||||
tree.Delete(Int64(tripleID))
|
||||
tree := ts.index.Tree(d, id)
|
||||
tree.Delete(tid)
|
||||
}
|
||||
|
||||
for d := quad.Subject; d <= quad.Label; d++ {
|
||||
|
|
@ -208,7 +195,7 @@ func (ts *TripleStore) RemoveTriple(t quad.Quad) {
|
|||
if d == quad.Label && t.Get(d) == "" {
|
||||
continue
|
||||
}
|
||||
nodeTree := ts.index.GetOrCreate(d, id)
|
||||
nodeTree := ts.index.Tree(d, id)
|
||||
if nodeTree.Len() != 0 {
|
||||
stillExists = true
|
||||
break
|
||||
|
|
@ -229,7 +216,7 @@ func (ts *TripleStore) TripleIterator(d quad.Direction, value graph.Value) graph
|
|||
index, ok := ts.index.Get(d, value.(int64))
|
||||
data := fmt.Sprintf("dir:%s val:%d", d, value.(int64))
|
||||
if ok {
|
||||
return NewLlrbIterator(index, data)
|
||||
return NewIterator(index, data)
|
||||
}
|
||||
return &iterator.Null{}
|
||||
}
|
||||
|
|
@ -271,4 +258,5 @@ func (ts *TripleStore) TripleDirection(val graph.Value, d quad.Direction) graph.
|
|||
func (ts *TripleStore) NodesAllIterator() graph.Iterator {
|
||||
return NewMemstoreAllIterator(ts)
|
||||
}
|
||||
|
||||
func (ts *TripleStore) Close() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue