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:
kortschak 2014-08-05 22:41:25 +09:30
parent 1ae81e6d00
commit 6acfdcc5d6
19 changed files with 183 additions and 183 deletions

View file

@ -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) {

View file

@ -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 {