From 545a0cff4bc7ed8ee4fd448fc59b52e8908bc1d1 Mon Sep 17 00:00:00 2001 From: Matt Jaffee Date: Fri, 10 Feb 2017 09:11:23 -0600 Subject: [PATCH] Revert "pilosactl builds - fixed compatibility with pql changes" This reverts commit d6e2be97b1c294ee8587d643ef95a71ca47e6824. --- bench/query.go | 163 ++++++++++++++++++++++++++++++++ bench/randquery.go | 119 +++++++++++++++++++++++ bench/sliceheight.go | 2 +- cmd/pilosactl/main.go | 3 + cmd/pilosactl/slice-height.json | 2 +- 5 files changed, 287 insertions(+), 2 deletions(-) create mode 100644 bench/query.go create mode 100644 bench/randquery.go diff --git a/bench/query.go b/bench/query.go new file mode 100644 index 000000000..aae645e18 --- /dev/null +++ b/bench/query.go @@ -0,0 +1,163 @@ +package bench + +import ( + "math/rand" + + "github.com/pilosa/pilosa/pql" +) + +// NewQueryGenerator initializes a new QueryGenerator +func NewQueryGenerator(seed int64) *QueryGenerator { + return &QueryGenerator{ + IDToFrameFn: func(id uint64) string { return "frame.n" }, + R: rand.New(rand.NewSource(seed)), + Frames: []string{"frame.n"}, + } +} + +// QueryGenerator holds the configuration and state for randomly generating +// queries. +type QueryGenerator struct { + IDToFrameFn func(id uint64) string + R *rand.Rand + Frames []string +} + +// Random returns a randomly generated query. +func (q *QueryGenerator) Random(maxN, depth, maxargs int, idmin, idmax uint64) pql.Call { + // TODO: handle depth==1 or 0 + val := q.R.Intn(5) + switch val { + case 0: + return q.RandomTopN(maxN, depth, maxargs, idmin, idmax) + default: + return q.RandomBitmapCall(depth, maxargs, idmin, idmax) + } +} + +// RandomTopN returns a randomly generated TopN query. +func (q *QueryGenerator) RandomTopN(maxN, depth, maxargs int, idmin, idmax uint64) *pql.TopN { + frameIdx := q.R.Intn(len(q.Frames)) + return &pql.TopN{ + Frame: q.Frames[frameIdx], + N: q.R.Intn(maxN-1) + 1, + Src: q.RandomBitmapCall(depth, maxargs, idmin, idmax), + } +} + +// RandomBitmapCall returns a randomly generate query which is a pql.BitmapCall. +func (q *QueryGenerator) RandomBitmapCall(depth, maxargs int, idmin, idmax uint64) pql.BitmapCall { + if depth <= 1 { + bitmapID := q.R.Int63n(int64(idmax)-int64(idmin)) + int64(idmin) + return Bitmap(uint64(bitmapID), q.IDToFrameFn(uint64(bitmapID))) + } + call := q.R.Intn(4) + if call == 0 { + return q.RandomBitmapCall(1, 0, idmin, idmax) + } + + var numargs int + if maxargs <= 2 { + numargs = 2 + } else { + numargs = q.R.Intn(maxargs-2) + 2 + } + calls := make([]pql.BitmapCall, numargs) + for i := 0; i < numargs; i++ { + calls[i] = q.RandomBitmapCall(depth-1, maxargs, idmin, idmax) + } + + switch call { + case 1: + return Difference(calls...) + case 2: + return Intersect(calls...) + case 3: + return Union(calls...) + } + return nil +} + +/////////////////////////////////////////////////// +// Helpers TODO: move elsewhere +/////////////////////////////////////////////////// + +func ClearBit(id uint64, frame string, profileID uint64) *pql.ClearBit { + return &pql.ClearBit{ + ID: id, + Frame: frame, + ProfileID: profileID, + } +} + +func Count(bm pql.BitmapCall) *pql.Count { + return &pql.Count{ + Input: bm, + } +} + +func Profile(id uint64) *pql.Profile { + return &pql.Profile{ + ID: id, + } +} + +func SetBit(id uint64, frame string, profileID uint64) *pql.SetBit { + return &pql.SetBit{ + ID: id, + Frame: frame, + ProfileID: profileID, + } +} + +func SetBitmapAttrs(id uint64, frame string, attrs map[string]interface{}) *pql.SetBitmapAttrs { + return &pql.SetBitmapAttrs{ + ID: id, + Frame: frame, + Attrs: attrs, + } +} + +func SetProfileAttrs(id uint64, attrs map[string]interface{}) *pql.SetProfileAttrs { + return &pql.SetProfileAttrs{ + ID: id, + Attrs: attrs, + } +} + +func TopN(frame string, n int, src pql.BitmapCall, bmids []uint64, field string, filters []interface{}) *pql.TopN { + return &pql.TopN{ + Frame: frame, + N: n, + Src: src, + BitmapIDs: bmids, + Field: field, + Filters: filters, + } +} + +func Difference(bms ...pql.BitmapCall) *pql.Difference { + // TODO does this need to be limited to two inputs? + return &pql.Difference{ + Inputs: bms, + } +} + +func Intersect(bms ...pql.BitmapCall) *pql.Intersect { + return &pql.Intersect{ + Inputs: bms, + } +} + +func Union(bms ...pql.BitmapCall) *pql.Union { + return &pql.Union{ + Inputs: bms, + } +} + +func Bitmap(id uint64, frame string) *pql.Bitmap { + return &pql.Bitmap{ + ID: id, + Frame: frame, + } +} diff --git a/bench/randquery.go b/bench/randquery.go new file mode 100644 index 000000000..8bdc98e74 --- /dev/null +++ b/bench/randquery.go @@ -0,0 +1,119 @@ +package bench + +import ( + "context" + "flag" + "fmt" + "io/ioutil" + "strings" + "time" +) + +// RandomQuery queries randomly and deterministically based on a seed. +type RandomQuery 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 *RandomQuery) Init(hosts []string, agentNum int) error { + b.Name = "random-query" + b.Seed = b.Seed + int64(agentNum) + return b.HasClient.Init(hosts, agentNum) +} + +// Usage returns the usage message to be printed. +func (b *RandomQuery) Usage() string { + return ` +random-query constructs random queries + +Agent number modifies the random seed. + +Usage: random-query [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' + + -content-type string + protobuf or pql +`[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 *RandomQuery) ConsumeFlags(args []string) ([]string, error) { + fs := flag.NewFlagSet("RandomQuery", 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", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") + + if err := fs.Parse(args); err != nil { + return nil, err + } + b.DBs = strings.Split(dbs, ",") + return fs.Args(), nil +} + +// Run runs the RandomQuery benchmark +func (b *RandomQuery) Run(ctx context.Context) map[string]interface{} { + results := make(map[string]interface{}) + if b.client == nil { + results["error"] = fmt.Errorf("No client set for RandomQuery") + 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() + 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/bench/sliceheight.go b/bench/sliceheight.go index da83979e2..dbfdd144f 100644 --- a/bench/sliceheight.go +++ b/bench/sliceheight.go @@ -125,7 +125,7 @@ func (b *SliceHeight) Run(ctx context.Context) map[string]interface{} { iresults["import"] = imp.Run(ctx) qstart := time.Now() - q := &pql.Call{Name: "TopN", Args: map[string]interface{}{"frame": b.Frame, "n": 50}} + q := &pql.TopN{Frame: b.Frame, N: 50} _, err := imp.Client.ExecuteQuery(ctx, b.Database, q.String(), true) if err != nil { iresults["query_error"] = err.Error() diff --git a/cmd/pilosactl/main.go b/cmd/pilosactl/main.go index 73a0bff7f..331459c31 100644 --- a/cmd/pilosactl/main.go +++ b/cmd/pilosactl/main.go @@ -1246,6 +1246,8 @@ func (cmd *BagentCommand) ParseFlags(args []string) error { bm = &bench.Zipf{} case "multi-db-set-bits": bm = &bench.MultiDBSetBits{} + case "random-query": + bm = &bench.RandomQuery{} case "import": bm = bench.NewImport(cmd.Stdin, cmd.Stdout, cmd.Stderr) case "slice-height": @@ -1291,6 +1293,7 @@ The following flags are allowed: random-set-bits zipf multi-db-set-bits + random-query import slice-height `) diff --git a/cmd/pilosactl/slice-height.json b/cmd/pilosactl/slice-height.json index 49b11e280..ac77e501b 100644 --- a/cmd/pilosactl/slice-height.json +++ b/cmd/pilosactl/slice-height.json @@ -2,7 +2,7 @@ "benchmarks": [ { "num": 1, - "args": ["-human", "slice-height", "-max-time", "30", "-max-bits-per-map", "100"] + "args": ["-human", "slice-height", "-max-time", "1", "-max-bits-per-map", "100"] } ] }