Use concrete value for quad.Quad
Comparison of -short benchmarks in cayley.
$ benchcmp pointer.bench concrete.bench
benchmark old ns/op new ns/op delta
BenchmarkNamePredicate 1673276 1655093 -1.09%
BenchmarkLargeSetsNoIntersection 318985907 261499984 -18.02%
BenchmarkNetAndSpeed 104403743 41516981 -60.23%
BenchmarkKeanuAndNet 17309258 16857513 -2.61%
BenchmarkKeanuAndSpeed 20159161 19282833 -4.35%
Comparison of pathological cases are not so happy.
benchmark old ns/op new ns/op delta
BenchmarkVeryLargeSetsSmallIntersection 55269775527 246084606672 +345.24%
BenchmarkHelplessContainsChecker 23436501319 24308906949 +3.72%
Profiling the worst case:
Pointer:
Total: 6121 samples
1973 32.2% 32.2% 1973 32.2% runtime.findfunc
773 12.6% 44.9% 773 12.6% readvarint
510 8.3% 53.2% 511 8.3% step
409 6.7% 59.9% 410 6.7% runtime.gentraceback
390 6.4% 66.2% 391 6.4% pcvalue
215 3.5% 69.8% 215 3.5% runtime.funcdata
181 3.0% 72.7% 181 3.0% checkframecopy
118 1.9% 74.6% 119 1.9% runtime.funcspdelta
96 1.6% 76.2% 96 1.6% runtime.topofstack
76 1.2% 77.5% 76 1.2% scanblock
Concrete:
Total: 25027 samples
9437 37.7% 37.7% 9437 37.7% runtime.findfunc
3853 15.4% 53.1% 3853 15.4% readvarint
2366 9.5% 62.6% 2366 9.5% step
2186 8.7% 71.3% 2186 8.7% runtime.gentraceback
1816 7.3% 78.5% 1816 7.3% pcvalue
1016 4.1% 82.6% 1016 4.1% runtime.funcdata
859 3.4% 86.0% 859 3.4% checkframecopy
506 2.0% 88.1% 506 2.0% runtime.funcspdelta
410 1.6% 89.7% 410 1.6% runtime.topofstack
303 1.2% 90.9% 303 1.2% runtime.newstack
This commit is contained in:
parent
1ae81e6d00
commit
6acfdcc5d6
19 changed files with 183 additions and 183 deletions
|
|
@ -36,11 +36,11 @@ func (qs *store) ValueOf(s string) graph.Value {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (qs *store) AddTriple(*quad.Quad) {}
|
||||
func (qs *store) AddTriple(quad.Quad) {}
|
||||
|
||||
func (qs *store) AddTripleSet([]*quad.Quad) {}
|
||||
func (qs *store) AddTripleSet([]quad.Quad) {}
|
||||
|
||||
func (qs *store) Quad(graph.Value) *quad.Quad { return &quad.Quad{} }
|
||||
func (qs *store) Quad(graph.Value) quad.Quad { return quad.Quad{} }
|
||||
|
||||
func (qs *store) TripleIterator(d quad.Direction, i graph.Value) graph.Iterator {
|
||||
return qs.iter
|
||||
|
|
@ -74,4 +74,4 @@ func (qs *store) Close() {}
|
|||
|
||||
func (qs *store) TripleDirection(graph.Value, quad.Direction) graph.Value { return 0 }
|
||||
|
||||
func (qs *store) RemoveTriple(t *quad.Quad) {}
|
||||
func (qs *store) RemoveTriple(t quad.Quad) {}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ import (
|
|||
"github.com/google/cayley/quad"
|
||||
)
|
||||
|
||||
func makeTripleSet() []*quad.Quad {
|
||||
tripleSet := []*quad.Quad{
|
||||
func makeTripleSet() []quad.Quad {
|
||||
tripleSet := []quad.Quad{
|
||||
{"A", "follows", "B", ""},
|
||||
{"C", "follows", "B", ""},
|
||||
{"C", "follows", "D", ""},
|
||||
|
|
@ -43,7 +43,7 @@ func makeTripleSet() []*quad.Quad {
|
|||
return tripleSet
|
||||
}
|
||||
|
||||
func iteratedTriples(qs graph.TripleStore, it graph.Iterator) []*quad.Quad {
|
||||
func iteratedTriples(qs graph.TripleStore, it graph.Iterator) []quad.Quad {
|
||||
var res ordered
|
||||
for {
|
||||
val, ok := graph.Next(it)
|
||||
|
|
@ -56,7 +56,7 @@ func iteratedTriples(qs graph.TripleStore, it graph.Iterator) []*quad.Quad {
|
|||
return res
|
||||
}
|
||||
|
||||
type ordered []*quad.Quad
|
||||
type ordered []quad.Quad
|
||||
|
||||
func (o ordered) Len() int { return len(o) }
|
||||
func (o ordered) Less(i, j int) bool {
|
||||
|
|
@ -143,7 +143,7 @@ func TestLoadDatabase(t *testing.T) {
|
|||
t.Error("Failed to create leveldb TripleStore.")
|
||||
}
|
||||
|
||||
qs.AddTriple(&quad.Quad{"Something", "points_to", "Something Else", "context"})
|
||||
qs.AddTriple(quad.Quad{"Something", "points_to", "Something Else", "context"})
|
||||
for _, pq := range []string{"Something", "points_to", "Something Else", "context"} {
|
||||
if got := qs.NameOf(qs.ValueOf(pq)); got != pq {
|
||||
t.Errorf("Failed to roundtrip %q, got:%q expect:%q", pq, got, pq)
|
||||
|
|
@ -176,7 +176,7 @@ func TestLoadDatabase(t *testing.T) {
|
|||
t.Errorf("Unexpected triplestore size, got:%d expect:5", s)
|
||||
}
|
||||
|
||||
qs.RemoveTriple(&quad.Quad{"A", "follows", "B", ""})
|
||||
qs.RemoveTriple(quad.Quad{"A", "follows", "B", ""})
|
||||
if s := qs.Size(); s != 10 {
|
||||
t.Errorf("Unexpected triplestore size after RemoveTriple, got:%d expect:10", s)
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ func TestSetIterator(t *testing.T) {
|
|||
|
||||
qs.AddTripleSet(makeTripleSet())
|
||||
|
||||
expect := []*quad.Quad{
|
||||
expect := []quad.Quad{
|
||||
{"C", "follows", "B", ""},
|
||||
{"C", "follows", "D", ""},
|
||||
}
|
||||
|
|
@ -326,7 +326,7 @@ func TestSetIterator(t *testing.T) {
|
|||
// Object iterator.
|
||||
it = qs.TripleIterator(quad.Object, qs.ValueOf("F"))
|
||||
|
||||
expect = []*quad.Quad{
|
||||
expect = []quad.Quad{
|
||||
{"B", "follows", "F", ""},
|
||||
{"E", "follows", "F", ""},
|
||||
}
|
||||
|
|
@ -339,7 +339,7 @@ func TestSetIterator(t *testing.T) {
|
|||
and.AddSubIterator(qs.TripleIterator(quad.Subject, qs.ValueOf("B")))
|
||||
and.AddSubIterator(it)
|
||||
|
||||
expect = []*quad.Quad{
|
||||
expect = []quad.Quad{
|
||||
{"B", "follows", "F", ""},
|
||||
}
|
||||
if got := iteratedTriples(qs, and); !reflect.DeepEqual(got, expect) {
|
||||
|
|
@ -349,7 +349,7 @@ func TestSetIterator(t *testing.T) {
|
|||
// Predicate iterator.
|
||||
it = qs.TripleIterator(quad.Predicate, qs.ValueOf("status"))
|
||||
|
||||
expect = []*quad.Quad{
|
||||
expect = []quad.Quad{
|
||||
{"B", "status", "cool", "status_graph"},
|
||||
{"D", "status", "cool", "status_graph"},
|
||||
{"G", "status", "cool", "status_graph"},
|
||||
|
|
@ -362,7 +362,7 @@ func TestSetIterator(t *testing.T) {
|
|||
// Label iterator.
|
||||
it = qs.TripleIterator(quad.Label, qs.ValueOf("status_graph"))
|
||||
|
||||
expect = []*quad.Quad{
|
||||
expect = []quad.Quad{
|
||||
{"B", "status", "cool", "status_graph"},
|
||||
{"D", "status", "cool", "status_graph"},
|
||||
{"G", "status", "cool", "status_graph"},
|
||||
|
|
@ -378,7 +378,7 @@ func TestSetIterator(t *testing.T) {
|
|||
and.AddSubIterator(qs.TripleIterator(quad.Subject, qs.ValueOf("B")))
|
||||
and.AddSubIterator(it)
|
||||
|
||||
expect = []*quad.Quad{
|
||||
expect = []quad.Quad{
|
||||
{"B", "status", "cool", "status_graph"},
|
||||
}
|
||||
if got := iteratedTriples(qs, and); !reflect.DeepEqual(got, expect) {
|
||||
|
|
@ -391,7 +391,7 @@ func TestSetIterator(t *testing.T) {
|
|||
and.AddSubIterator(it)
|
||||
and.AddSubIterator(qs.TripleIterator(quad.Subject, qs.ValueOf("B")))
|
||||
|
||||
expect = []*quad.Quad{
|
||||
expect = []quad.Quad{
|
||||
{"B", "status", "cool", "status_graph"},
|
||||
}
|
||||
if got := iteratedTriples(qs, and); !reflect.DeepEqual(got, expect) {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func (qs *TripleStore) Size() int64 {
|
|||
return qs.size
|
||||
}
|
||||
|
||||
func (qs *TripleStore) createKeyFor(d [3]quad.Direction, triple *quad.Quad) []byte {
|
||||
func (qs *TripleStore) createKeyFor(d [3]quad.Direction, triple quad.Quad) []byte {
|
||||
key := make([]byte, 0, 2+(qs.hasher.Size()*3))
|
||||
// TODO(kortschak) Remove dependence on String() method.
|
||||
key = append(key, []byte{d[0].Prefix(), d[1].Prefix()}...)
|
||||
|
|
@ -126,7 +126,7 @@ func (qs *TripleStore) createKeyFor(d [3]quad.Direction, triple *quad.Quad) []by
|
|||
return key
|
||||
}
|
||||
|
||||
func (qs *TripleStore) createProvKeyFor(d [3]quad.Direction, triple *quad.Quad) []byte {
|
||||
func (qs *TripleStore) createProvKeyFor(d [3]quad.Direction, triple quad.Quad) []byte {
|
||||
key := make([]byte, 0, 2+(qs.hasher.Size()*4))
|
||||
// TODO(kortschak) Remove dependence on String() method.
|
||||
key = append(key, []byte{quad.Label.Prefix(), d[0].Prefix()}...)
|
||||
|
|
@ -144,7 +144,7 @@ func (qs *TripleStore) createValueKeyFor(s string) []byte {
|
|||
return key
|
||||
}
|
||||
|
||||
func (qs *TripleStore) AddTriple(t *quad.Quad) {
|
||||
func (qs *TripleStore) AddTriple(t quad.Quad) {
|
||||
batch := &leveldb.Batch{}
|
||||
qs.buildWrite(batch, t)
|
||||
err := qs.db.Write(batch, qs.writeopts)
|
||||
|
|
@ -163,7 +163,7 @@ var (
|
|||
pso = [3]quad.Direction{quad.Predicate, quad.Subject, quad.Object}
|
||||
)
|
||||
|
||||
func (qs *TripleStore) RemoveTriple(t *quad.Quad) {
|
||||
func (qs *TripleStore) RemoveTriple(t quad.Quad) {
|
||||
_, err := qs.db.Get(qs.createKeyFor(spo, t), qs.readopts)
|
||||
if err != nil && err != leveldb.ErrNotFound {
|
||||
glog.Error("Couldn't access DB to confirm deletion")
|
||||
|
|
@ -192,8 +192,8 @@ func (qs *TripleStore) RemoveTriple(t *quad.Quad) {
|
|||
qs.size--
|
||||
}
|
||||
|
||||
func (qs *TripleStore) buildTripleWrite(batch *leveldb.Batch, t *quad.Quad) {
|
||||
bytes, err := json.Marshal(*t)
|
||||
func (qs *TripleStore) buildTripleWrite(batch *leveldb.Batch, t quad.Quad) {
|
||||
bytes, err := json.Marshal(t)
|
||||
if err != nil {
|
||||
glog.Errorf("Couldn't write to buffer for triple %s: %s", t, err)
|
||||
return
|
||||
|
|
@ -206,7 +206,7 @@ func (qs *TripleStore) buildTripleWrite(batch *leveldb.Batch, t *quad.Quad) {
|
|||
}
|
||||
}
|
||||
|
||||
func (qs *TripleStore) buildWrite(batch *leveldb.Batch, t *quad.Quad) {
|
||||
func (qs *TripleStore) buildWrite(batch *leveldb.Batch, t quad.Quad) {
|
||||
qs.buildTripleWrite(batch, t)
|
||||
qs.UpdateValueKeyBy(t.Get(quad.Subject), 1, nil)
|
||||
qs.UpdateValueKeyBy(t.Get(quad.Predicate), 1, nil)
|
||||
|
|
@ -267,7 +267,7 @@ func (qs *TripleStore) UpdateValueKeyBy(name string, amount int, batch *leveldb.
|
|||
}
|
||||
}
|
||||
|
||||
func (qs *TripleStore) AddTripleSet(t_s []*quad.Quad) {
|
||||
func (qs *TripleStore) AddTripleSet(t_s []quad.Quad) {
|
||||
batch := &leveldb.Batch{}
|
||||
newTs := len(t_s)
|
||||
resizeMap := make(map[string]int)
|
||||
|
|
@ -306,23 +306,23 @@ func (qs *TripleStore) Close() {
|
|||
qs.open = false
|
||||
}
|
||||
|
||||
func (qs *TripleStore) Quad(k graph.Value) *quad.Quad {
|
||||
func (qs *TripleStore) Quad(k graph.Value) quad.Quad {
|
||||
var triple quad.Quad
|
||||
b, err := qs.db.Get(k.([]byte), qs.readopts)
|
||||
if err != nil && err != leveldb.ErrNotFound {
|
||||
glog.Error("Error: couldn't get triple from DB.")
|
||||
return &quad.Quad{}
|
||||
return quad.Quad{}
|
||||
}
|
||||
if err == leveldb.ErrNotFound {
|
||||
// No harm, no foul.
|
||||
return &quad.Quad{}
|
||||
return quad.Quad{}
|
||||
}
|
||||
err = json.Unmarshal(b, &triple)
|
||||
if err != nil {
|
||||
glog.Error("Error: couldn't reconstruct triple.")
|
||||
return &quad.Quad{}
|
||||
return quad.Quad{}
|
||||
}
|
||||
return &triple
|
||||
return triple
|
||||
}
|
||||
|
||||
func (qs *TripleStore) convertStringToByteHash(s string) []byte {
|
||||
|
|
|
|||
|
|
@ -101,13 +101,13 @@ func newTripleStore() *TripleStore {
|
|||
return &ts
|
||||
}
|
||||
|
||||
func (ts *TripleStore) AddTripleSet(triples []*quad.Quad) {
|
||||
func (ts *TripleStore) AddTripleSet(triples []quad.Quad) {
|
||||
for _, t := range triples {
|
||||
ts.AddTriple(t)
|
||||
}
|
||||
}
|
||||
|
||||
func (ts *TripleStore) tripleExists(t *quad.Quad) (bool, int64) {
|
||||
func (ts *TripleStore) tripleExists(t quad.Quad) (bool, int64) {
|
||||
smallest := -1
|
||||
var smallest_tree *llrb.LLRB
|
||||
for d := quad.Subject; d <= quad.Label; d++ {
|
||||
|
|
@ -137,19 +137,19 @@ func (ts *TripleStore) tripleExists(t *quad.Quad) (bool, int64) {
|
|||
if !ok {
|
||||
break
|
||||
}
|
||||
if t.Equals(&ts.triples[val.(int64)]) {
|
||||
if t.Equals(ts.triples[val.(int64)]) {
|
||||
return true, val.(int64)
|
||||
}
|
||||
}
|
||||
return false, 0
|
||||
}
|
||||
|
||||
func (ts *TripleStore) AddTriple(t *quad.Quad) {
|
||||
func (ts *TripleStore) AddTriple(t quad.Quad) {
|
||||
if exists, _ := ts.tripleExists(t); exists {
|
||||
return
|
||||
}
|
||||
var tripleID int64
|
||||
ts.triples = append(ts.triples, *t)
|
||||
ts.triples = append(ts.triples, t)
|
||||
tripleID = ts.tripleIdCounter
|
||||
ts.size++
|
||||
ts.tripleIdCounter++
|
||||
|
|
@ -178,7 +178,7 @@ func (ts *TripleStore) AddTriple(t *quad.Quad) {
|
|||
// TODO(barakmich): Add VIP indexing
|
||||
}
|
||||
|
||||
func (ts *TripleStore) RemoveTriple(t *quad.Quad) {
|
||||
func (ts *TripleStore) RemoveTriple(t quad.Quad) {
|
||||
var tripleID int64
|
||||
var exists bool
|
||||
tripleID = 0
|
||||
|
|
@ -224,8 +224,8 @@ func (ts *TripleStore) RemoveTriple(t *quad.Quad) {
|
|||
}
|
||||
}
|
||||
|
||||
func (ts *TripleStore) Quad(index graph.Value) *quad.Quad {
|
||||
return &ts.triples[index.(int64)]
|
||||
func (ts *TripleStore) Quad(index graph.Value) quad.Quad {
|
||||
return ts.triples[index.(int64)]
|
||||
}
|
||||
|
||||
func (ts *TripleStore) TripleIterator(d quad.Direction, value graph.Value) graph.Iterator {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import (
|
|||
// \-->|#D#|------------->+---+
|
||||
// +---+
|
||||
//
|
||||
var simpleGraph = []*quad.Quad{
|
||||
var simpleGraph = []quad.Quad{
|
||||
{"A", "follows", "B", ""},
|
||||
{"C", "follows", "B", ""},
|
||||
{"C", "follows", "D", ""},
|
||||
|
|
@ -51,7 +51,7 @@ var simpleGraph = []*quad.Quad{
|
|||
{"G", "status", "cool", "status_graph"},
|
||||
}
|
||||
|
||||
func makeTestStore(data []*quad.Quad) (*TripleStore, []pair) {
|
||||
func makeTestStore(data []quad.Quad) (*TripleStore, []pair) {
|
||||
seen := make(map[string]struct{})
|
||||
ts := newTripleStore()
|
||||
var (
|
||||
|
|
@ -175,7 +175,7 @@ func TestLinksToOptimization(t *testing.T) {
|
|||
func TestRemoveTriple(t *testing.T) {
|
||||
ts, _ := makeTestStore(simpleGraph)
|
||||
|
||||
ts.RemoveTriple(&quad.Quad{"E", "follows", "F", ""})
|
||||
ts.RemoveTriple(quad.Quad{"E", "follows", "F", ""})
|
||||
|
||||
fixed := ts.FixedIterator()
|
||||
fixed.Add(ts.ValueOf("E"))
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func newTripleStore(addr string, options graph.Options) (graph.TripleStore, erro
|
|||
return &qs, nil
|
||||
}
|
||||
|
||||
func (qs *TripleStore) getIdForTriple(t *quad.Quad) string {
|
||||
func (qs *TripleStore) getIdForTriple(t quad.Quad) string {
|
||||
id := qs.ConvertStringToByteHash(t.Subject)
|
||||
id += qs.ConvertStringToByteHash(t.Predicate)
|
||||
id += qs.ConvertStringToByteHash(t.Object)
|
||||
|
|
@ -150,7 +150,7 @@ func (qs *TripleStore) updateNodeBy(node_name string, inc int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (qs *TripleStore) writeTriple(t *quad.Quad) bool {
|
||||
func (qs *TripleStore) writeTriple(t quad.Quad) bool {
|
||||
tripledoc := bson.M{
|
||||
"_id": qs.getIdForTriple(t),
|
||||
"Subject": t.Subject,
|
||||
|
|
@ -170,7 +170,7 @@ func (qs *TripleStore) writeTriple(t *quad.Quad) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (qs *TripleStore) AddTriple(t *quad.Quad) {
|
||||
func (qs *TripleStore) AddTriple(t quad.Quad) {
|
||||
_ = qs.writeTriple(t)
|
||||
qs.updateNodeBy(t.Subject, 1)
|
||||
qs.updateNodeBy(t.Predicate, 1)
|
||||
|
|
@ -180,7 +180,7 @@ func (qs *TripleStore) AddTriple(t *quad.Quad) {
|
|||
}
|
||||
}
|
||||
|
||||
func (qs *TripleStore) AddTripleSet(in []*quad.Quad) {
|
||||
func (qs *TripleStore) AddTripleSet(in []quad.Quad) {
|
||||
qs.session.SetSafe(nil)
|
||||
ids := make(map[string]int)
|
||||
for _, t := range in {
|
||||
|
|
@ -200,7 +200,7 @@ func (qs *TripleStore) AddTripleSet(in []*quad.Quad) {
|
|||
qs.session.SetSafe(&mgo.Safe{})
|
||||
}
|
||||
|
||||
func (qs *TripleStore) RemoveTriple(t *quad.Quad) {
|
||||
func (qs *TripleStore) RemoveTriple(t quad.Quad) {
|
||||
err := qs.db.C("triples").RemoveId(qs.getIdForTriple(t))
|
||||
if err == mgo.ErrNotFound {
|
||||
return
|
||||
|
|
@ -216,13 +216,13 @@ func (qs *TripleStore) RemoveTriple(t *quad.Quad) {
|
|||
}
|
||||
}
|
||||
|
||||
func (qs *TripleStore) Quad(val graph.Value) *quad.Quad {
|
||||
func (qs *TripleStore) Quad(val graph.Value) quad.Quad {
|
||||
var bsonDoc bson.M
|
||||
err := qs.db.C("triples").FindId(val.(string)).One(&bsonDoc)
|
||||
if err != nil {
|
||||
glog.Errorf("Error: Couldn't retrieve triple %s %v", val, err)
|
||||
}
|
||||
return &quad.Quad{
|
||||
return quad.Quad{
|
||||
bsonDoc["Subject"].(string),
|
||||
bsonDoc["Predicate"].(string),
|
||||
bsonDoc["Object"].(string),
|
||||
|
|
|
|||
|
|
@ -40,17 +40,17 @@ type Value interface{}
|
|||
|
||||
type TripleStore interface {
|
||||
// Add a triple to the store.
|
||||
AddTriple(*quad.Quad)
|
||||
AddTriple(quad.Quad)
|
||||
|
||||
// Add a set of triples to the store, atomically if possible.
|
||||
AddTripleSet([]*quad.Quad)
|
||||
AddTripleSet([]quad.Quad)
|
||||
|
||||
// Removes a triple matching the given one from the database,
|
||||
// if it exists. Does nothing otherwise.
|
||||
RemoveTriple(*quad.Quad)
|
||||
RemoveTriple(quad.Quad)
|
||||
|
||||
// Given an opaque token, returns the triple for that token from the store.
|
||||
Quad(Value) *quad.Quad
|
||||
Quad(Value) quad.Quad
|
||||
|
||||
// Given a direction and a token, creates an iterator of links which have
|
||||
// that node token in that directional field.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue