Skip to content
Snippets Groups Projects
Commit 40194a67 authored by Pawan Rawal's avatar Pawan Rawal
Browse files

Benchmarking

1. Exporting query and result byte slices inside SubGraph so that they are
written to file when we write the SubGraph to file after gobencoding it.
2. Added benchmark test to benchmark ToJSON and ToProtocolBuffer methods for
actors and directors query for 10,100 and 1000 entities in the result.
parent 69f0e9dd
No related branches found
No related tags found
No related merge requests found
The files in this folder contain gobencoded data for a processed SubGraph for
the following queries. The number at the end(10,100,1000) of the files
represents the number of entities in the results of the query.
Actors query
{
me(_xid_:m.08624h) {
type.object.name.en
film.actor.film {
film.performance.film {
type.object.name.en
}
}
}
}
Directors query
{
me(_xid_:m.05dxl_) {
type.object.name.en
film.director.film {
film.film.genre {
type.object.name.en
}
}
}
}
Benchmarking tests were run for ToJson and ToProtocolBuffer methods. Results
from the `go test` command are tabulated below.
BenchmarkToJson 500 3939003 ns/op 957723 B/op 16115 allocs/op
BenchmarkToProtocolBuffer 1000 2288681 ns/op 566287 B/op 7542 allocs/op
We can see that ToProtocolBuffer method allocates less memory and takes lesser
time than ToJson method.
\ No newline at end of file
File added
File added
File added
File added
File added
File added
......@@ -115,8 +115,8 @@ type SubGraph struct {
Offset int
Children []*SubGraph
query []byte
result []byte
Query []byte
Result []byte
}
func mergeInterfaces(i1 interface{}, i2 interface{}) interface{} {
......@@ -138,7 +138,7 @@ func mergeInterfaces(i1 interface{}, i2 interface{}) interface{} {
}
func postTraverse(g *SubGraph) (result map[uint64]interface{}, rerr error) {
if len(g.query) == 0 {
if len(g.Query) == 0 {
return result, nil
}
......@@ -163,13 +163,13 @@ func postTraverse(g *SubGraph) (result map[uint64]interface{}, rerr error) {
}
// Now read the query and results at current node.
uo := flatbuffers.GetUOffsetT(g.query)
uo := flatbuffers.GetUOffsetT(g.Query)
q := new(task.Query)
q.Init(g.query, uo)
q.Init(g.Query, uo)
ro := flatbuffers.GetUOffsetT(g.result)
ro := flatbuffers.GetUOffsetT(g.Result)
r := new(task.Result)
r.Init(g.result, ro)
r.Init(g.Result, ro)
if q.UidsLength() != r.UidmatrixLength() {
glog.Fatalf("Result uidmatrixlength: %v. Query uidslength: %v",
......@@ -277,18 +277,19 @@ func indexOf(uid uint64, q *task.Query) int {
// This method gets the values and children for a subgraph.
func (g *SubGraph) preTraverse(uid uint64, dst *graph.Node) error {
properties := make(map[string]*graph.Value)
var properties map[string]*graph.Value
properties = make(map[string]*graph.Value)
var children []*graph.Node
// We go through all predicate children of the subgraph.
for _, pc := range g.Children {
ro := flatbuffers.GetUOffsetT(pc.result)
ro := flatbuffers.GetUOffsetT(pc.Result)
r := new(task.Result)
r.Init(pc.result, ro)
r.Init(pc.Result, ro)
uo := flatbuffers.GetUOffsetT(pc.query)
uo := flatbuffers.GetUOffsetT(pc.Query)
q := new(task.Query)
q.Init(pc.query, uo)
q.Init(pc.Query, uo)
idx := indexOf(uid, q)
......@@ -354,13 +355,13 @@ func (g *SubGraph) preTraverse(uid uint64, dst *graph.Node) error {
func (g *SubGraph) ToProtocolBuffer(l *Latency) (n *graph.Node, rerr error) {
n = &graph.Node{}
n.Attribute = g.Attr
if len(g.query) == 0 {
if len(g.Query) == 0 {
return n, nil
}
ro := flatbuffers.GetUOffsetT(g.result)
ro := flatbuffers.GetUOffsetT(g.Result)
r := new(task.Result)
r.Init(g.result, ro)
r.Init(g.Result, ro)
var ul task.UidList
r.Uidmatrix(&ul, 0)
......@@ -448,9 +449,9 @@ func newGraph(euid uint64, exid string) (*SubGraph, error) {
sg := new(SubGraph)
sg.Attr = "_root_"
sg.result = b.Bytes[b.Head():]
sg.Result = b.Bytes[b.Head():]
// Also add query for consistency and to allow for ToJson() later.
sg.query = createTaskQuery(sg, []uint64{euid})
sg.Query = createTaskQuery(sg, []uint64{euid})
return sg, nil
}
......@@ -535,8 +536,8 @@ func ProcessGraph(sg *SubGraph, rch chan error, td time.Duration) {
timeout := time.Now().Add(td)
var err error
if len(sg.query) > 0 && sg.Attr != "_root_" {
sg.result, err = worker.ProcessTaskOverNetwork(sg.query)
if len(sg.Query) > 0 && sg.Attr != "_root_" {
sg.Result, err = worker.ProcessTaskOverNetwork(sg.Query)
if err != nil {
x.Err(glog, err).Error("While processing task.")
rch <- err
......@@ -544,9 +545,9 @@ func ProcessGraph(sg *SubGraph, rch chan error, td time.Duration) {
}
}
uo := flatbuffers.GetUOffsetT(sg.result)
uo := flatbuffers.GetUOffsetT(sg.Result)
r := new(task.Result)
r.Init(sg.result, uo)
r.Init(sg.Result, uo)
if r.ValuesLength() > 0 {
var v task.Value
......@@ -589,7 +590,7 @@ func ProcessGraph(sg *SubGraph, rch chan error, td time.Duration) {
childchan := make(chan error, len(sg.Children))
for i := 0; i < len(sg.Children); i++ {
child := sg.Children[i]
child.query = createTaskQuery(child, sorted)
child.Query = createTaskQuery(child, sorted)
go ProcessGraph(child, childchan, timeleft)
}
......
......@@ -17,6 +17,8 @@
package query
import (
"bytes"
"encoding/gob"
"fmt"
"io/ioutil"
"os"
......@@ -63,12 +65,12 @@ func checkName(t *testing.T, r *task.Result, idx int, expected string) {
func checkSingleValue(t *testing.T, child *SubGraph,
attr string, value string) {
if child.Attr != attr || len(child.result) == 0 {
t.Error("Expected attr name with some result")
if child.Attr != attr || len(child.Result) == 0 {
t.Error("Expected attr name with some.Result")
}
uo := flatbuffers.GetUOffsetT(child.result)
uo := flatbuffers.GetUOffsetT(child.Result)
r := new(task.Result)
r.Init(child.result, uo)
r.Init(child.Result, uo)
if r.ValuesLength() != 1 {
t.Errorf("Expected value length 1. Got: %v", r.ValuesLength())
}
......@@ -105,9 +107,9 @@ func TestNewGraph(t *testing.T) {
worker.Init(ps, nil, 0, 1)
uo := flatbuffers.GetUOffsetT(sg.result)
uo := flatbuffers.GetUOffsetT(sg.Result)
r := new(task.Result)
r.Init(sg.result, uo)
r.Init(sg.Result, uo)
if r.UidmatrixLength() != 1 {
t.Errorf("Expected length 1. Got: %v", r.UidmatrixLength())
}
......@@ -230,13 +232,13 @@ func TestProcessGraph(t *testing.T) {
if child.Attr != "friend" {
t.Errorf("Expected attr friend. Got: %v", child.Attr)
}
if len(child.result) == 0 {
t.Errorf("Expected some result.")
if len(child.Result) == 0 {
t.Errorf("Expected some.Result.")
return
}
uo := flatbuffers.GetUOffsetT(child.result)
uo := flatbuffers.GetUOffsetT(child.Result)
r := new(task.Result)
r.Init(child.result, uo)
r.Init(child.Result, uo)
if r.UidmatrixLength() != 1 {
t.Errorf("Expected 1 matrix. Got: %v", r.UidmatrixLength())
......@@ -257,8 +259,8 @@ func TestProcessGraph(t *testing.T) {
t.Errorf("Expected attr name")
}
child = child.Children[0]
uo = flatbuffers.GetUOffsetT(child.result)
r.Init(child.result, uo)
uo = flatbuffers.GetUOffsetT(child.Result)
r.Init(child.Result, uo)
if r.ValuesLength() != 5 {
t.Errorf("Expected 5 names of 5 friends")
}
......@@ -420,3 +422,71 @@ func TestToProtocolBuffer(t *testing.T) {
t.Errorf("Expected 0 children, Got: %v", len(child.Children))
}
}
func benchmarkToJson(file string, b *testing.B) {
b.ReportAllocs()
var sg SubGraph
var l Latency
f, err := ioutil.ReadFile(file)
if err != nil {
b.Error(err)
}
buf := bytes.NewBuffer(f)
dec := gob.NewDecoder(buf)
err = dec.Decode(&sg)
if err != nil {
b.Error(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := sg.ToJson(&l); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkToJson(b *testing.B) {
benchmarkToJson("benchmark/actors10.txt", b)
benchmarkToJson("benchmark/actors100.txt", b)
benchmarkToJson("benchmark/actors1000.txt", b)
benchmarkToJson("benchmark/directors10.txt", b)
benchmarkToJson("benchmark/directors100.txt", b)
benchmarkToJson("benchmark/directors1000.txt", b)
}
func benchmarkToProtocolBuffer(file string, b *testing.B) {
b.ReportAllocs()
var sg SubGraph
var l Latency
f, err := ioutil.ReadFile(file)
if err != nil {
b.Error(err)
}
buf := bytes.NewBuffer(f)
dec := gob.NewDecoder(buf)
err = dec.Decode(&sg)
if err != nil {
b.Error(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := sg.ToProtocolBuffer(&l); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkToProtocolBuffer(b *testing.B) {
benchmarkToProtocolBuffer("benchmark/actors10.txt", b)
benchmarkToProtocolBuffer("benchmark/actors100.txt", b)
benchmarkToProtocolBuffer("benchmark/actors1000.txt", b)
benchmarkToProtocolBuffer("benchmark/directors10.txt", b)
benchmarkToProtocolBuffer("benchmark/directors100.txt", b)
benchmarkToProtocolBuffer("benchmark/directors1000.txt", b)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment