mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
define Benchmarker interface and a benchmark
This commit is contained in:
parent
172b2643a2
commit
6f3232dc6e
2 changed files with 79 additions and 137 deletions
79
bench/bench.go
Normal file
79
bench/bench.go
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue