mirror of https://github.com/tidwall/tile38.git
Add bench tests for knn
This commit is contained in:
parent
2a4272c95f
commit
fe6e3863ba
|
@ -2,6 +2,7 @@ package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -429,3 +430,19 @@ func match(expectIn string) func(org, v interface{}) (resp, expect interface{})
|
||||||
return fmt.Sprintf("%v", org), expectIn
|
return fmt.Sprintf("%v", org), expectIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func subBenchSearch(b *testing.B, mc *mockServer) {
|
||||||
|
runBenchStep(b, mc, "KNN", keys_KNN_bench)
|
||||||
|
}
|
||||||
|
|
||||||
|
func keys_KNN_bench(mc *mockServer) error {
|
||||||
|
lat := rand.Float64()*180 - 90
|
||||||
|
lon := rand.Float64()*360 - 180
|
||||||
|
_, err := mc.conn.Do("NEARBY",
|
||||||
|
"mykey",
|
||||||
|
"LIMIT", 50,
|
||||||
|
"DISTANCE",
|
||||||
|
"POINTS",
|
||||||
|
"POINT", lat, lon)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -20,15 +20,19 @@ import (
|
||||||
|
|
||||||
var errTimeout = errors.New("timeout")
|
var errTimeout = errors.New("timeout")
|
||||||
|
|
||||||
func mockCleanup() {
|
func mockCleanup(silent bool) {
|
||||||
|
if !silent {
|
||||||
fmt.Printf("Cleanup: may take some time... ")
|
fmt.Printf("Cleanup: may take some time... ")
|
||||||
|
}
|
||||||
files, _ := ioutil.ReadDir(".")
|
files, _ := ioutil.ReadDir(".")
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if strings.HasPrefix(file.Name(), "data-mock-") {
|
if strings.HasPrefix(file.Name(), "data-mock-") {
|
||||||
os.RemoveAll(file.Name())
|
os.RemoveAll(file.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !silent {
|
||||||
fmt.Printf("OK\n")
|
fmt.Printf("OK\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockServer struct {
|
type mockServer struct {
|
||||||
|
@ -39,11 +43,13 @@ type mockServer struct {
|
||||||
conn redis.Conn
|
conn redis.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockOpenServer() (*mockServer, error) {
|
func mockOpenServer(silent bool) (*mockServer, error) {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
port := rand.Int()%20000 + 20000
|
port := rand.Int()%20000 + 20000
|
||||||
dir := fmt.Sprintf("data-mock-%d", port)
|
dir := fmt.Sprintf("data-mock-%d", port)
|
||||||
|
if !silent {
|
||||||
fmt.Printf("Starting test server at port %d\n", port)
|
fmt.Printf("Starting test server at port %d\n", port)
|
||||||
|
}
|
||||||
logOutput := ioutil.Discard
|
logOutput := ioutil.Discard
|
||||||
if os.Getenv("PRINTLOG") == "1" {
|
if os.Getenv("PRINTLOG") == "1" {
|
||||||
logOutput = os.Stderr
|
logOutput = os.Stderr
|
||||||
|
|
|
@ -2,10 +2,14 @@ package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gomodule/redigo/redis"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -23,18 +27,18 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAll(t *testing.T) {
|
func TestAll(t *testing.T) {
|
||||||
mockCleanup()
|
mockCleanup(false)
|
||||||
defer mockCleanup()
|
defer mockCleanup(false)
|
||||||
|
|
||||||
ch := make(chan os.Signal)
|
ch := make(chan os.Signal)
|
||||||
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||||
go func() {
|
go func() {
|
||||||
<-ch
|
<-ch
|
||||||
mockCleanup()
|
mockCleanup(false)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
mc, err := mockOpenServer()
|
mc, err := mockOpenServer(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -83,3 +87,88 @@ func runStep(t *testing.T, mc *mockServer, name string, step func(mc *mockServer
|
||||||
fmt.Printf("["+green+"ok"+clear+"]: %s\n", name)
|
fmt.Printf("["+green+"ok"+clear+"]: %s\n", name)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkAll(b *testing.B) {
|
||||||
|
mockCleanup(true)
|
||||||
|
defer mockCleanup(true)
|
||||||
|
|
||||||
|
ch := make(chan os.Signal)
|
||||||
|
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
|
||||||
|
go func() {
|
||||||
|
<-ch
|
||||||
|
mockCleanup(true)
|
||||||
|
os.Exit(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
mc, err := mockOpenServer(true)
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
defer mc.Close()
|
||||||
|
runSubBenchmark(b, "search", mc, subBenchSearch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadBenchmarkPoints(b *testing.B, mc *mockServer) (err error) {
|
||||||
|
const nPoints = 200000
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
|
||||||
|
// add a bunch of points
|
||||||
|
for i := 0; i < nPoints; i++ {
|
||||||
|
val := fmt.Sprintf("val:%d", i)
|
||||||
|
var resp string
|
||||||
|
var lat, lon, fval float64
|
||||||
|
fval = rand.Float64()
|
||||||
|
lat = rand.Float64()*180 - 90
|
||||||
|
lon = rand.Float64()*360 - 180
|
||||||
|
resp, err = redis.String(mc.conn.Do("SET",
|
||||||
|
"mykey", val,
|
||||||
|
"FIELD", "foo", fval,
|
||||||
|
"POINT", lat, lon))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if resp != "OK" {
|
||||||
|
err = fmt.Errorf("expected 'OK', got '%s'", resp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func runSubBenchmark(b *testing.B, name string, mc *mockServer, bench func(t *testing.B, mc *mockServer)) {
|
||||||
|
b.Run(name, func(b *testing.B) {
|
||||||
|
bench(b, mc)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func runBenchStep(b *testing.B, mc *mockServer, name string, step func(mc *mockServer) error) {
|
||||||
|
b.Helper()
|
||||||
|
b.Run(name, func(b *testing.B) {
|
||||||
|
b.Helper()
|
||||||
|
if err := func() error {
|
||||||
|
// reset the current server
|
||||||
|
mc.ResetConn()
|
||||||
|
defer mc.ResetConn()
|
||||||
|
// clear the database so the test is consistent
|
||||||
|
if err := mc.DoBatch([][]interface{}{
|
||||||
|
{"OUTPUT", "resp"}, {"OK"},
|
||||||
|
{"FLUSHDB"}, {"OK"},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err := loadBenchmarkPoints(b, mc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if err := step(mc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}(); err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue