From 6f3232dc6e21dd6a4d07e03cd75ca79ddfa2aa47 Mon Sep 17 00:00:00 2001 From: jaffee Date: Fri, 4 Nov 2016 17:27:13 -0500 Subject: [PATCH] define Benchmarker interface and a benchmark --- bench/bench.go | 79 +++++++++++++++++++++ client_integration_test.go | 137 ------------------------------------- 2 files changed, 79 insertions(+), 137 deletions(-) create mode 100644 bench/bench.go delete mode 100644 client_integration_test.go diff --git a/bench/bench.go b/bench/bench.go new file mode 100644 index 000000000..c6238797b --- /dev/null +++ b/bench/bench.go @@ -0,0 +1,79 @@ +package bench + +import ( + "fmt" + + "github.com/umbel/pilosa" +) + +// Benchmarker is an interface to guide the creation of new pilosa benchmarks or +// benchmark components. It defines 2 methods, Init, and Run. These are separate +// methods so that benchmark running code can time only the running of the +// benchmark, and not any setup. +type Benchmarker interface { + // Init takes a list of hosts and is generally expected to set up a + // connection to pilosa using whatever client it chooses. + Init(hosts []string) error + + // Run runs the benchmark. It takes an agentNum which should be used to + // parameterize the benchmark if it is being run simultaneously on multiple + // "agents". E.G. the agentNum might be used to make a random seed different + // for each agent, or have each agent set a different set of bits. The return + // value of Run is kept generic so that any relevant statistics or metrics + // that may be specific to the benchmark in question can be reported. + Run(agentNum int) map[string]interface{} +} + +// SetBitBenchmark sets a bunch of bits in pilosa, and can be configured in a +// number of ways. +type SetBitBenchmark struct { + cli *pilosa.Client + // bits being set will all be greater than BaseBitmapID. + BaseBitmapID int + // profile ids used will all be greater than BaseProfileID. + BaseProfileID int + // Iterations is the number of bits that will be set by this Benchmark. + Iterations int + // Number of profiles to iterate through - in this way multiple bits may be + // set on the same profile. + NumProfiles int + // DB to use in pilosa. + DB string +} + +// Init connects to pilosa and sets the client on b. +func (b *SetBitBenchmark) Init(hosts []string) (err error) { + b.cli, err = pilosa.NewClient(hosts[0]) + if err != nil { + return err + } + if b.Iterations == 0 { + b.Iterations = 100 + } + if b.DB == "" { + b.DB = "SetBitBenchmark" + } + return nil +} + +// Run runs the SetBitBenchmark +func (b *SetBitBenchmark) Run(agentNum int) map[string]interface{} { + results := make(map[string]interface{}) + if b.cli == nil { + results["error"] = fmt.Errorf("No client set for SetBitBenchmark agent: %v", agentNum) + return results + } + for n := 0; n < b.Iterations; n++ { + iterID := agentizeNum(n, b.Iterations, agentNum) + query := fmt.Sprintf("SetBit(%d, 'frame.n', %d)", b.BaseBitmapID+iterID, b.BaseProfileID+iterID%b.NumProfiles) + b.cli.ExecuteQuery("2", query, true) + } + return results +} + +// agentizeNum is a helper which combines the loop iteration (n) with the total +// number of iterations and the agentNum in order to produce a globally unique +// number across all loop iterations on all agents. +func agentizeNum(n, iterations, agentNum int) int { + return n + (agentNum * iterations) +} diff --git a/client_integration_test.go b/client_integration_test.go deleted file mode 100644 index 64063cef8..000000000 --- a/client_integration_test.go +++ /dev/null @@ -1,137 +0,0 @@ -// +build integration - -package pilosa_test - -import ( - "fmt" - "io/ioutil" - "log" - "os" - "path/filepath" - "strconv" - "testing" - - "github.com/umbel/pilosa" -) - -// FIXME(jaffee): move all this cluster creation and interface code to a better place -type TestCluster interface { - Hosts() []string - Close() error -} - -type cluster struct { - hosts []string - servers []*pilosa.Server - cluster *pilosa.Cluster - path string -} - -func newTestCluster() *cluster { - return &cluster{ - hosts: make([]string, 0), - servers: make([]*pilosa.Server, 0), - } -} - -func (c *cluster) Hosts() []string { return c.hosts } -func (c *cluster) Close() error { - errs := "" - for _, s := range c.servers { - if err := s.Close(); err != nil { - errs = errs + err.Error() + "; " - } - } - if err := os.RemoveAll(c.path); err != nil { - errs = errs + err.Error() + ";" - } - if errs != "" { - return fmt.Errorf(errs) - } - return nil -} - -func setupCluster() (TestCluster, error) { - // FIXME(jaffee): add controls for configurable cluster setup via env vars or - // build tags. For now I just stole benbjohsnon's code from pilosa-bench - replicaN := 1 - serverN := 3 - BasePort := 19327 - - testCluster := newTestCluster() - - path, err := ioutil.TempDir("", "pilosa-bench-") - if err != nil { - return testCluster, err - } - testCluster.path = path - - // Build cluster configuration. - cluster := pilosa.NewCluster() - cluster.ReplicaN = replicaN - - for i := 0; i < serverN; i++ { - cluster.Nodes = append(cluster.Nodes, &pilosa.Node{ - Host: fmt.Sprintf("localhost:%d", BasePort+i), - }) - } - testCluster.cluster = cluster - - // Build servers. - servers := make([]*pilosa.Server, serverN) - for i := range servers { - // Make server work directory. - if err := os.MkdirAll(filepath.Join(path, strconv.Itoa(i)), 0777); err != nil { - return testCluster, err - } - - // Build server. - s := pilosa.NewServer() - s.Host = fmt.Sprintf("localhost:%d", BasePort+i) - s.Cluster = cluster - s.Index.Path = filepath.Join(path, strconv.Itoa(i), "data") - - // Create log file. - f, err := os.Create(filepath.Join(path, strconv.Itoa(i), "log")) - if err != nil { - return testCluster, err - } - - // Set log and optionally write out to stderr as well. - s.LogOutput = f - - servers[i] = s - } - testCluster.servers = servers - - // Open all servers. - for _, s := range servers { - log.Printf("opening : %v", s) - if err := s.Open(); err != nil { - return testCluster, err - } - } - - hosts := make([]string, 0) - for _, s := range servers { - hosts = append(hosts, s.Host) - } - testCluster.hosts = hosts - return testCluster, nil -} - -func BenchmarkSetBitOps(b *testing.B) { - tc, err := setupCluster() - defer tc.Close() - if err != nil { - b.Fatal(err) - } - cli, err := pilosa.NewClient(tc.Hosts()[0]) - if err != nil { - b.Fatal(err) - } - for n := 0; n < b.N; n++ { - query := fmt.Sprintf("SetBit(%d, 'frame.n', %d)", n, n%10) - cli.ExecuteQuery("2", query, true) - } -}