From dd5366889d68a51f8502516425cb829474119e15 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Thu, 19 Jan 2017 22:31:48 -0600 Subject: [PATCH 1/7] execute pql against db on server --- bench/pql.go | 117 ++++++++++++++++++++++++++++++++++++++++++ client.go | 32 ++++++++++++ cmd/pilosactl/main.go | 2 + 3 files changed, 151 insertions(+) create mode 100644 bench/pql.go diff --git a/bench/pql.go b/bench/pql.go new file mode 100644 index 000000000..0bfb5f2d8 --- /dev/null +++ b/bench/pql.go @@ -0,0 +1,117 @@ +package bench + +import ( + "context" + "flag" + "fmt" + "io/ioutil" + "strings" + "time" +) + +// RandomQuery queries randomly and deterministically based on a seed. +type RandomPql struct { + HasClient + Name string `json:"name"` + MaxDepth int `json:"max-depth"` + MaxArgs int `json:"max-args"` + MaxN int `json:"max-n"` + BaseBitmapID int64 `json:"base-bitmap-id"` + BitmapIDRange int64 `json:"bitmap-id-range"` + Iterations int `json:"iterations"` + Seed int64 `json:"seed"` + DBs []string `json:"dbs"` +} + +// Init adds the agent num to the random seed and initializes the client. +func (b *RandomPql) Init(hosts []string, agentNum int) error { + b.Name = "random-pql" + b.Seed = b.Seed + int64(agentNum) + return b.HasClient.Init(hosts, agentNum) +} + +// Usage returns the usage message to be printed. +func (b *RandomPql) Usage() string { + return ` +random-pql compare random queries between protobuf and pql + +Agent number modifies the random seed. + +Usage: random-pql[arguments] + +The following arguments are available: + + -max-depth int + Maximum nesting depth of queries + + -max-args int + Maximum number of args for Union/Intersect/Difference Queries + + -max-n int + Maximum N value for TopN queries. + + -base-bitmap-id int + bitmap id to start from + + -bitmap-id-range int + number of possible bitmap ids that can be set + + -iterations int + number of bits to set + + -seed int + Seed for RNG + + -dbs string + Comma separated list of DBs to query against + + -client-type string + Can be 'single' (all agents hitting one host) or 'round_robin' +`[1:] +} + +// ConsumeFlags parses all flags up to the next non flag argument (argument does +// not start with "-" and isn't the value of a flag). It returns the remaining +// args. +func (b *RandomPql) ConsumeFlags(args []string) ([]string, error) { + fs := flag.NewFlagSet("RandomPql", flag.ContinueOnError) + fs.SetOutput(ioutil.Discard) + fs.IntVar(&b.MaxDepth, "max-depth", 4, "") + fs.IntVar(&b.MaxArgs, "max-args", 4, "") + fs.IntVar(&b.MaxN, "max-n", 4, "") + fs.Int64Var(&b.BaseBitmapID, "base-bitmap-id", 0, "") + fs.Int64Var(&b.BitmapIDRange, "bitmap-id-range", 100000, "") + fs.Int64Var(&b.Seed, "seed", 1, "") + fs.IntVar(&b.Iterations, "iterations", 100, "") + var dbs string + fs.StringVar(&dbs, "dbs", "benchdb", "") + fs.StringVar(&b.ClientType, "client-type", "single", "") + + if err := fs.Parse(args); err != nil { + return nil, err + } + b.DBs = strings.Split(dbs, ",") + return fs.Args(), nil +} + +// Run runs the RandomPQL benchmark +func (b *RandomPql) Run(ctx context.Context) map[string]interface{} { + results := make(map[string]interface{}) + if b.client == nil { + results["error"] = fmt.Errorf("No client set") + return results + } + qm := NewQueryGenerator(b.Seed) + s := NewStats() + var start time.Time + for n := 0; n < b.Iterations; n++ { + call := qm.Random(b.MaxN, b.MaxDepth, b.MaxArgs, uint64(b.BaseBitmapID), uint64(b.BitmapIDRange)) + start = time.Now() + queryString := call.String() + b.client.ExecutePql(ctx, b.DBs[n%len(b.DBs)], queryString) + s.Add(time.Now().Sub(start)) + + } + AddToResults(s, results) + return results +} diff --git a/client.go b/client.go index d26206022..ce1f0c79f 100644 --- a/client.go +++ b/client.go @@ -194,6 +194,38 @@ func (c *Client) ExecuteQuery(ctx context.Context, db, query string, allowRedire return qresp, nil } +// ExecutePQL executes query string against db on the server. +func (c *Client) ExecutePql(ctx context.Context, db, query string) (interface{}, error) { + u := url.URL{ + Scheme: "http", + Host: c.host, + Path: "/query", + RawQuery: url.Values{ + "db": {db}, + }.Encode(), + } + + req, err := http.NewRequest("POST", u.String(), bytes.NewReader([]byte(query))) + if err != nil { + return nil, err + } + resp, err := c.HTTPClient.Do(req.WithContext(ctx)) + + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } else if resp.StatusCode != http.StatusOK { + return nil, errors.New(string(body)) + } + return string(body), nil + +} + // Import bulk imports bits for a single slice to a host. func (c *Client) Import(ctx context.Context, db, frame string, slice uint64, bits []Bit) error { if db == "" { diff --git a/cmd/pilosactl/main.go b/cmd/pilosactl/main.go index ec8651ab5..01947ec2c 100644 --- a/cmd/pilosactl/main.go +++ b/cmd/pilosactl/main.go @@ -1248,6 +1248,8 @@ func (cmd *BagentCommand) ParseFlags(args []string) error { bm = bench.NewImport(cmd.Stdin, cmd.Stdout, cmd.Stderr) case "slice-height": bm = bench.NewSliceHeight(cmd.Stdin, cmd.Stdout, cmd.Stderr) + case "random-pql": + bm = &bench.RandomPql{} default: return fmt.Errorf("Unknown benchmark cmd: %v", remArgs[0]) } From 8ddff3235f5c64906c7558229e8cb7dec51d1cd7 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Wed, 25 Jan 2017 00:14:20 -0600 Subject: [PATCH 2/7] add pql option to randquery --- bench/client.go | 25 +++++++-- bench/pql.go | 117 ------------------------------------------ bench/randquery.go | 18 ++++++- cmd/pilosactl/main.go | 2 - 4 files changed, 37 insertions(+), 125 deletions(-) delete mode 100644 bench/pql.go diff --git a/bench/client.go b/bench/client.go index 603e25cb2..0f975ac9c 100644 --- a/bench/client.go +++ b/bench/client.go @@ -19,11 +19,13 @@ func roundRobinClient(hosts []string, agentNum int) (*pilosa.Client, error) { return firstHostClient(hosts[clientNum:]) } + // HasClient provides a reusable component for Benchmark implementations which // provides the Init method, a ClientType argument and a cli internal variable. type HasClient struct { - client *pilosa.Client - ClientType string `json:"client-type"` + client *pilosa.Client + ClientType string `json:"client-type"` + ContentType string `json:"content-type"` } // Init for HasClient looks at the ClientType field and creates a pilosa client @@ -34,11 +36,24 @@ func (h *HasClient) Init(hosts []string, agentNum int) error { switch h.ClientType { case "single": h.client, err = firstHostClient(hosts) - return err case "round_robin": h.client, err = roundRobinClient(hosts, agentNum) - return err default: - return fmt.Errorf("Unsupported ClientType: %v", h.ClientType) + err = fmt.Errorf("Unsupported ClientType: %v", h.ClientType) + } + if err != nil { + return err + } + + switch h.ContentType { + case "protobuf": + return nil + case "pql": + return nil + default: + return fmt.Errorf("Unsupported ContentType: %v", h.ContentType) + } } + + diff --git a/bench/pql.go b/bench/pql.go deleted file mode 100644 index 0bfb5f2d8..000000000 --- a/bench/pql.go +++ /dev/null @@ -1,117 +0,0 @@ -package bench - -import ( - "context" - "flag" - "fmt" - "io/ioutil" - "strings" - "time" -) - -// RandomQuery queries randomly and deterministically based on a seed. -type RandomPql struct { - HasClient - Name string `json:"name"` - MaxDepth int `json:"max-depth"` - MaxArgs int `json:"max-args"` - MaxN int `json:"max-n"` - BaseBitmapID int64 `json:"base-bitmap-id"` - BitmapIDRange int64 `json:"bitmap-id-range"` - Iterations int `json:"iterations"` - Seed int64 `json:"seed"` - DBs []string `json:"dbs"` -} - -// Init adds the agent num to the random seed and initializes the client. -func (b *RandomPql) Init(hosts []string, agentNum int) error { - b.Name = "random-pql" - b.Seed = b.Seed + int64(agentNum) - return b.HasClient.Init(hosts, agentNum) -} - -// Usage returns the usage message to be printed. -func (b *RandomPql) Usage() string { - return ` -random-pql compare random queries between protobuf and pql - -Agent number modifies the random seed. - -Usage: random-pql[arguments] - -The following arguments are available: - - -max-depth int - Maximum nesting depth of queries - - -max-args int - Maximum number of args for Union/Intersect/Difference Queries - - -max-n int - Maximum N value for TopN queries. - - -base-bitmap-id int - bitmap id to start from - - -bitmap-id-range int - number of possible bitmap ids that can be set - - -iterations int - number of bits to set - - -seed int - Seed for RNG - - -dbs string - Comma separated list of DBs to query against - - -client-type string - Can be 'single' (all agents hitting one host) or 'round_robin' -`[1:] -} - -// ConsumeFlags parses all flags up to the next non flag argument (argument does -// not start with "-" and isn't the value of a flag). It returns the remaining -// args. -func (b *RandomPql) ConsumeFlags(args []string) ([]string, error) { - fs := flag.NewFlagSet("RandomPql", flag.ContinueOnError) - fs.SetOutput(ioutil.Discard) - fs.IntVar(&b.MaxDepth, "max-depth", 4, "") - fs.IntVar(&b.MaxArgs, "max-args", 4, "") - fs.IntVar(&b.MaxN, "max-n", 4, "") - fs.Int64Var(&b.BaseBitmapID, "base-bitmap-id", 0, "") - fs.Int64Var(&b.BitmapIDRange, "bitmap-id-range", 100000, "") - fs.Int64Var(&b.Seed, "seed", 1, "") - fs.IntVar(&b.Iterations, "iterations", 100, "") - var dbs string - fs.StringVar(&dbs, "dbs", "benchdb", "") - fs.StringVar(&b.ClientType, "client-type", "single", "") - - if err := fs.Parse(args); err != nil { - return nil, err - } - b.DBs = strings.Split(dbs, ",") - return fs.Args(), nil -} - -// Run runs the RandomPQL benchmark -func (b *RandomPql) Run(ctx context.Context) map[string]interface{} { - results := make(map[string]interface{}) - if b.client == nil { - results["error"] = fmt.Errorf("No client set") - return results - } - qm := NewQueryGenerator(b.Seed) - s := NewStats() - var start time.Time - for n := 0; n < b.Iterations; n++ { - call := qm.Random(b.MaxN, b.MaxDepth, b.MaxArgs, uint64(b.BaseBitmapID), uint64(b.BitmapIDRange)) - start = time.Now() - queryString := call.String() - b.client.ExecutePql(ctx, b.DBs[n%len(b.DBs)], queryString) - s.Add(time.Now().Sub(start)) - - } - AddToResults(s, results) - return results -} diff --git a/bench/randquery.go b/bench/randquery.go index 11fa7016b..20573bc3f 100644 --- a/bench/randquery.go +++ b/bench/randquery.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "strings" "time" + "errors" ) // RandomQuery queries randomly and deterministically based on a seed. @@ -67,6 +68,9 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + + -content-type string + protobuf or pql `[1:] } @@ -86,6 +90,7 @@ func (b *RandomQuery) ConsumeFlags(args []string) ([]string, error) { var dbs string fs.StringVar(&dbs, "dbs", "benchdb", "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err @@ -107,9 +112,20 @@ func (b *RandomQuery) Run(ctx context.Context) map[string]interface{} { for n := 0; n < b.Iterations; n++ { call := qm.Random(b.MaxN, b.MaxDepth, b.MaxArgs, uint64(b.BaseBitmapID), uint64(b.BitmapIDRange)) start = time.Now() - b.client.ExecuteQuery(ctx, b.DBs[n%len(b.DBs)], call.String(), true) + b.ExecuteQuery(b.ContentType, b.DBs[n % len(b.DBs)], call.String(), ctx) s.Add(time.Now().Sub(start)) } AddToResults(s, results) return results } + +func (b *RandomQuery) ExecuteQuery(contentType, db, query string, ctx context.Context, ) (interface{}, error) { + if contentType == "protobuf" { + return b.client.ExecuteQuery(ctx, db, query, true) + } else if contentType == "pql" { + fmt.Println("HERRR") + return b.client.ExecutePql(ctx, db, query) + } else { + return nil, errors.New("unsupport content type") + } +} diff --git a/cmd/pilosactl/main.go b/cmd/pilosactl/main.go index 01947ec2c..ec8651ab5 100644 --- a/cmd/pilosactl/main.go +++ b/cmd/pilosactl/main.go @@ -1248,8 +1248,6 @@ func (cmd *BagentCommand) ParseFlags(args []string) error { bm = bench.NewImport(cmd.Stdin, cmd.Stdout, cmd.Stderr) case "slice-height": bm = bench.NewSliceHeight(cmd.Stdin, cmd.Stdout, cmd.Stderr) - case "random-pql": - bm = &bench.RandomPql{} default: return fmt.Errorf("Unknown benchmark cmd: %v", remArgs[0]) } From 6198acba8e3e2de7d6691a6a875037054db7976c Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Wed, 25 Jan 2017 00:17:19 -0600 Subject: [PATCH 3/7] ExecutePQL --- bench/randquery.go | 3 +-- client.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bench/randquery.go b/bench/randquery.go index 20573bc3f..e2e8aca03 100644 --- a/bench/randquery.go +++ b/bench/randquery.go @@ -123,8 +123,7 @@ func (b *RandomQuery) ExecuteQuery(contentType, db, query string, ctx context.Co if contentType == "protobuf" { return b.client.ExecuteQuery(ctx, db, query, true) } else if contentType == "pql" { - fmt.Println("HERRR") - return b.client.ExecutePql(ctx, db, query) + return b.client.ExecutePQL(ctx, db, query) } else { return nil, errors.New("unsupport content type") } diff --git a/client.go b/client.go index ce1f0c79f..2a2266000 100644 --- a/client.go +++ b/client.go @@ -195,7 +195,7 @@ func (c *Client) ExecuteQuery(ctx context.Context, db, query string, allowRedire } // ExecutePQL executes query string against db on the server. -func (c *Client) ExecutePql(ctx context.Context, db, query string) (interface{}, error) { +func (c *Client) ExecutePQL(ctx context.Context, db, query string) (interface{}, error) { u := url.URL{ Scheme: "http", Host: c.host, From 254eb8d24581619bdb742ccb3730718a1600063f Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Fri, 27 Jan 2017 12:13:17 -0600 Subject: [PATCH 4/7] move ExecuteQuery to client that every other benchmark can use --- bench/client.go | 13 ++++++++++++- bench/randquery.go | 10 ---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/bench/client.go b/bench/client.go index 0f975ac9c..805e287eb 100644 --- a/bench/client.go +++ b/bench/client.go @@ -2,8 +2,9 @@ package bench import ( "fmt" - "github.com/pilosa/pilosa" + "context" + "errors" ) func firstHostClient(hosts []string) (*pilosa.Client, error) { @@ -56,4 +57,14 @@ func (h *HasClient) Init(hosts []string, agentNum int) error { } } +func (h *HasClient) ExecuteQuery(contentType, db, query string, ctx context.Context) (interface{}, error) { + if contentType == "protobuf" { + return h.client.ExecuteQuery(ctx, db, query, true) + } else if contentType == "pql" { + return h.client.ExecutePQL(ctx, db, query) + } else { + return nil, errors.New("unsupport content type") + } +} + diff --git a/bench/randquery.go b/bench/randquery.go index e2e8aca03..936a6ca07 100644 --- a/bench/randquery.go +++ b/bench/randquery.go @@ -7,7 +7,6 @@ import ( "io/ioutil" "strings" "time" - "errors" ) // RandomQuery queries randomly and deterministically based on a seed. @@ -119,12 +118,3 @@ func (b *RandomQuery) Run(ctx context.Context) map[string]interface{} { return results } -func (b *RandomQuery) ExecuteQuery(contentType, db, query string, ctx context.Context, ) (interface{}, error) { - if contentType == "protobuf" { - return b.client.ExecuteQuery(ctx, db, query, true) - } else if contentType == "pql" { - return b.client.ExecutePQL(ctx, db, query) - } else { - return nil, errors.New("unsupport content type") - } -} From b571812307204c595ee3dcd8f48feaa0600a960a Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Fri, 27 Jan 2017 13:41:19 -0600 Subject: [PATCH 5/7] default content-type for benchmarks --- bench/diagonal.go | 3 +++ bench/multidb.go | 4 ++++ bench/random.go | 4 ++++ bench/zipf.go | 3 +++ 4 files changed, 14 insertions(+) diff --git a/bench/diagonal.go b/bench/diagonal.go index 4cb0e354c..393b732b3 100644 --- a/bench/diagonal.go +++ b/bench/diagonal.go @@ -57,6 +57,8 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + -content-type string + protobuf or pql `[1:] } @@ -71,6 +73,7 @@ func (b *DiagonalSetBits) ConsumeFlags(args []string) ([]string, error) { fs.IntVar(&b.Iterations, "iterations", 100, "") fs.StringVar(&b.DB, "db", "benchdb", "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/bench/multidb.go b/bench/multidb.go index 8ea8cd135..aa275ac17 100644 --- a/bench/multidb.go +++ b/bench/multidb.go @@ -49,6 +49,9 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + -content-type string + protobuf or pql + `[1:] } @@ -62,6 +65,7 @@ func (b *MultiDBSetBits) ConsumeFlags(args []string) ([]string, error) { fs.IntVar(&b.BaseProfileID, "base-profile-id", 0, "") fs.IntVar(&b.Iterations, "iterations", 100, "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/bench/random.go b/bench/random.go index e3e89400c..3bb74e886 100644 --- a/bench/random.go +++ b/bench/random.go @@ -65,6 +65,9 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + + -content-type string + protobuf or pql `[1:] } @@ -82,6 +85,7 @@ func (b *RandomSetBits) ConsumeFlags(args []string) ([]string, error) { fs.IntVar(&b.Iterations, "iterations", 100, "") fs.StringVar(&b.DB, "db", "benchdb", "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/bench/zipf.go b/bench/zipf.go index 6343cd4c6..7bd48ed1f 100644 --- a/bench/zipf.go +++ b/bench/zipf.go @@ -86,6 +86,8 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + -content-type string + protobuf or pql `[1:] } @@ -107,6 +109,7 @@ func (b *ZipfSetBits) ConsumeFlags(args []string) ([]string, error) { fs.Float64Var(&b.ProfileExponent, "profile-exponent", 1.01, "") fs.Float64Var(&b.ProfileRatio, "profile-ratio", 0.25, "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err From 3c1e262642932ed67a14522bf17a94072197d3c8 Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Fri, 27 Jan 2017 15:39:17 -0600 Subject: [PATCH 6/7] gofmt --- bench/client.go | 9 +++------ bench/randquery.go | 3 +-- client.go | 6 +++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/bench/client.go b/bench/client.go index 805e287eb..101f62d4b 100644 --- a/bench/client.go +++ b/bench/client.go @@ -1,10 +1,10 @@ package bench import ( - "fmt" - "github.com/pilosa/pilosa" "context" "errors" + "fmt" + "github.com/pilosa/pilosa" ) func firstHostClient(hosts []string) (*pilosa.Client, error) { @@ -20,12 +20,11 @@ func roundRobinClient(hosts []string, agentNum int) (*pilosa.Client, error) { return firstHostClient(hosts[clientNum:]) } - // HasClient provides a reusable component for Benchmark implementations which // provides the Init method, a ClientType argument and a cli internal variable. type HasClient struct { client *pilosa.Client - ClientType string `json:"client-type"` + ClientType string `json:"client-type"` ContentType string `json:"content-type"` } @@ -66,5 +65,3 @@ func (h *HasClient) ExecuteQuery(contentType, db, query string, ctx context.Cont return nil, errors.New("unsupport content type") } } - - diff --git a/bench/randquery.go b/bench/randquery.go index 936a6ca07..8bdc98e74 100644 --- a/bench/randquery.go +++ b/bench/randquery.go @@ -111,10 +111,9 @@ func (b *RandomQuery) Run(ctx context.Context) map[string]interface{} { for n := 0; n < b.Iterations; n++ { call := qm.Random(b.MaxN, b.MaxDepth, b.MaxArgs, uint64(b.BaseBitmapID), uint64(b.BitmapIDRange)) start = time.Now() - b.ExecuteQuery(b.ContentType, b.DBs[n % len(b.DBs)], call.String(), ctx) + b.ExecuteQuery(b.ContentType, b.DBs[n%len(b.DBs)], call.String(), ctx) s.Add(time.Now().Sub(start)) } AddToResults(s, results) return results } - diff --git a/client.go b/client.go index 2a2266000..5c24920ff 100644 --- a/client.go +++ b/client.go @@ -198,10 +198,10 @@ func (c *Client) ExecuteQuery(ctx context.Context, db, query string, allowRedire func (c *Client) ExecutePQL(ctx context.Context, db, query string) (interface{}, error) { u := url.URL{ Scheme: "http", - Host: c.host, - Path: "/query", + Host: c.host, + Path: "/query", RawQuery: url.Values{ - "db": {db}, + "db": {db}, }.Encode(), } From 2358e7714118463ca87eeff93c4b524cfbaa169e Mon Sep 17 00:00:00 2001 From: Linh Vo Date: Fri, 27 Jan 2017 15:57:01 -0600 Subject: [PATCH 7/7] another go fmt --- bench/zipf.go | 1 + 1 file changed, 1 insertion(+) diff --git a/bench/zipf.go b/bench/zipf.go index 71f83e10e..46832a75f 100644 --- a/bench/zipf.go +++ b/bench/zipf.go @@ -90,6 +90,7 @@ The following arguments are available: -operation string Can be 'set' or 'clear' + -content-type string protobuf or pql `[1:]