Added output from tests
Tested tests and fixed errors Adjusted default values
This commit is contained in:
parent
02fa79e9ce
commit
6c6595b2a0
32
burstTest.go
32
burstTest.go
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -15,14 +16,22 @@ getBurstTest starts goroutines for getRedis at the burstRateLimit per second
|
|||||||
*/
|
*/
|
||||||
func getBurstTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Duration) {
|
func getBurstTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Duration) {
|
||||||
durationChannel := make(chan bool, 1)
|
durationChannel := make(chan bool, 1)
|
||||||
burstRateLimiter := time.Tick(time.Second)
|
burstRateLimiter := time.Tick(time.Millisecond * 250)
|
||||||
|
timesChan := make(chan time.Duration)
|
||||||
|
errorChan := make(chan bool)
|
||||||
|
endChan := make(chan bool)
|
||||||
|
totalErrorChan := make(chan int)
|
||||||
|
totalTimeChan := make(chan []int64)
|
||||||
|
quaterRate := math.Abs(float64(rate) / 4)
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; i < int(duration.Seconds()); i++ {
|
for i := 0; i < int(duration.Seconds()); i++ {
|
||||||
<-time.Tick(time.Second)
|
<-time.Tick(time.Second)
|
||||||
}
|
}
|
||||||
durationChannel <- true
|
durationChannel <- true
|
||||||
}()
|
}()
|
||||||
fmt.Println("Starting burst test at", rate, "requests per second...")
|
|
||||||
|
go keepTotal(timesChan, errorChan, endChan, totalTimeChan, totalErrorChan)
|
||||||
|
fmt.Println("Starting burst test at", quaterRate, "requests per 250 milliseconds...")
|
||||||
end := false
|
end := false
|
||||||
for {
|
for {
|
||||||
if end {
|
if end {
|
||||||
@ -32,11 +41,26 @@ func getBurstTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.D
|
|||||||
case <-durationChannel:
|
case <-durationChannel:
|
||||||
end = true
|
end = true
|
||||||
case <-burstRateLimiter:
|
case <-burstRateLimiter:
|
||||||
for i := 0; i < rate; i++ {
|
for i := float64(0); i < quaterRate; i++ {
|
||||||
|
//this might need toggled
|
||||||
|
time.Sleep(time.Millisecond * 5)
|
||||||
key := rand.Intn(keyMaxValue)
|
key := rand.Intn(keyMaxValue)
|
||||||
go getRedis(rdbPtr, key)
|
go getRedis(rdbPtr, key, timesChan, errorChan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
endChan <- true
|
||||||
|
totalTimesFloat := <-totalTimeChan
|
||||||
|
totalErrors := <-totalErrorChan
|
||||||
|
errorRate := totalErrors / len(totalTimesFloat)
|
||||||
|
totalTimes := intToFloat(totalTimesFloat)
|
||||||
|
mean, stddev, perc99, perc95 := getResponseTimes(totalTimes)
|
||||||
fmt.Println("Burst test concluded...")
|
fmt.Println("Burst test concluded...")
|
||||||
|
fmt.Println("Total Requests:", len(totalTimesFloat))
|
||||||
|
fmt.Println("Error Rate:", errorRate, "ms")
|
||||||
|
fmt.Println("Mean:", mean, "ms")
|
||||||
|
fmt.Println("Standard Deviation:", stddev, "ms")
|
||||||
|
fmt.Println("95 Percentile:", perc95, "ms")
|
||||||
|
fmt.Println("99 Percentile:", perc99, "ms")
|
||||||
}
|
}
|
||||||
|
25
rateTest.go
25
rateTest.go
@ -17,10 +17,17 @@ Then starts goroutines for getRedis at that interval
|
|||||||
*/
|
*/
|
||||||
func getRateTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Duration) {
|
func getRateTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Duration) {
|
||||||
durationChannel := make(chan bool, 1)
|
durationChannel := make(chan bool, 1)
|
||||||
x := int(math.Abs(60 / float64(rate) * 10000000))
|
x := int(math.Abs(100 / float64(rate) * 10000000))
|
||||||
rateLimiter := time.Tick(time.Duration(x))
|
rateLimiter := time.Tick(time.Duration(x))
|
||||||
|
|
||||||
fmt.Println("Starting Test at", rateLimiter, "milliseconds per request...")
|
timesChan := make(chan time.Duration)
|
||||||
|
errorChan := make(chan bool)
|
||||||
|
endChan := make(chan bool)
|
||||||
|
totalErrorChan := make(chan int)
|
||||||
|
totalTimeChan := make(chan []int64)
|
||||||
|
|
||||||
|
go keepTotal(timesChan, errorChan, endChan, totalTimeChan, totalErrorChan)
|
||||||
|
fmt.Println("Starting Test at", time.Duration(x), "milliseconds per request...")
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; i < int(duration.Seconds()); i++ {
|
for i := 0; i < int(duration.Seconds()); i++ {
|
||||||
<-time.Tick(time.Second)
|
<-time.Tick(time.Second)
|
||||||
@ -39,8 +46,20 @@ func getRateTest(rdbPtr *redis.Conn, rate int, keyMaxValue int, duration time.Du
|
|||||||
end = true
|
end = true
|
||||||
case <-rateLimiter:
|
case <-rateLimiter:
|
||||||
key := rand.Intn(keyMaxValue)
|
key := rand.Intn(keyMaxValue)
|
||||||
go getRedis(rdbPtr, key)
|
go getRedis(rdbPtr, key, timesChan, errorChan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
endChan <- true
|
||||||
|
totalTimesFloat := <-totalTimeChan
|
||||||
|
totalErrors := <-totalErrorChan
|
||||||
|
errorRate := totalErrors / len(totalTimesFloat)
|
||||||
|
totalTimes := intToFloat(totalTimesFloat)
|
||||||
|
mean, stddev, perc99, perc95 := getResponseTimes(totalTimes)
|
||||||
fmt.Println("Rate test concluded...")
|
fmt.Println("Rate test concluded...")
|
||||||
|
fmt.Println("Total Requests:", len(totalTimesFloat))
|
||||||
|
fmt.Println("Error Rate:", errorRate, "ms")
|
||||||
|
fmt.Println("Mean:", mean, "ms")
|
||||||
|
fmt.Println("Standard Deviation:", stddev, "ms")
|
||||||
|
fmt.Println("95 Percentile:", perc95, "ms")
|
||||||
|
fmt.Println("99 Percentile:", perc99, "ms")
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,7 +14,7 @@ returns err from database connection
|
|||||||
*/
|
*/
|
||||||
func newPool(host string, username string, password string) *redis.Pool {
|
func newPool(host string, username string, password string) *redis.Pool {
|
||||||
return &redis.Pool{
|
return &redis.Pool{
|
||||||
MaxIdle: 80,
|
MaxIdle: 12000,
|
||||||
MaxActive: 12000,
|
MaxActive: 12000,
|
||||||
Dial: func() (redis.Conn, error) {
|
Dial: func() (redis.Conn, error) {
|
||||||
c, err := redis.Dial("tcp", host)
|
c, err := redis.Dial("tcp", host)
|
||||||
@ -44,7 +43,7 @@ setRateTest sets key/value into database
|
|||||||
@param key int redis key for the storage
|
@param key int redis key for the storage
|
||||||
@param value string string for the value to store
|
@param value string string for the value to store
|
||||||
*/
|
*/
|
||||||
func setRedis(rdbPtr *redis.Conn, key int, value string, waitGroup *sync.WaitGroup) {
|
func setRedis(rdbPtr *redis.Conn, key int, value string) {
|
||||||
rdb := *rdbPtr
|
rdb := *rdbPtr
|
||||||
//defer waitGroup.Done()
|
//defer waitGroup.Done()
|
||||||
_, err := rdb.Do("Set", key, value)
|
_, err := rdb.Do("Set", key, value)
|
||||||
@ -61,11 +60,10 @@ buildTestData iterates through a goroutine of setRedis to build test data into t
|
|||||||
*/
|
*/
|
||||||
func buildTestData(rdbPtr *redis.Conn, size int) {
|
func buildTestData(rdbPtr *redis.Conn, size int) {
|
||||||
fmt.Println("Initializing Test Data...")
|
fmt.Println("Initializing Test Data...")
|
||||||
var waitGroup sync.WaitGroup
|
for i := 1; i < size; i++ {
|
||||||
for i := 1; i < 50000; i++ {
|
|
||||||
key := i
|
key := i
|
||||||
value := "ThisIsATestStringThatShouldBeReplacedWithSomethingMoreRandomMaybeFromAnInputOrCSV"
|
value := "ThisIsATestStringThatShouldBeReplacedWithSomethingMoreRandomMaybeFromAnInputOrCSV"
|
||||||
setRedis(rdbPtr, key, value, &waitGroup)
|
setRedis(rdbPtr, key, value)
|
||||||
}
|
}
|
||||||
fmt.Println("Database Initialized...")
|
fmt.Println("Database Initialized...")
|
||||||
}
|
}
|
||||||
@ -75,10 +73,14 @@ getRedis queries the redis database for value of key
|
|||||||
@param rdbPtr connection is a pointer to the redis connection
|
@param rdbPtr connection is a pointer to the redis connection
|
||||||
@param key int is key value to query in database
|
@param key int is key value to query in database
|
||||||
*/
|
*/
|
||||||
func getRedis(rdbPtr *redis.Conn, key int) {
|
func getRedis(rdbPtr *redis.Conn, key int, timesChan chan time.Duration, errorChan chan bool) {
|
||||||
rdb := *rdbPtr
|
rdb := *rdbPtr
|
||||||
|
startTime := time.Now()
|
||||||
_, err := rdb.Do("Get", key)
|
_, err := rdb.Do("Get", key)
|
||||||
|
responseTime := time.Now().Sub(startTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errorChan <- true
|
||||||
fmt.Println("Unhandled error:", err)
|
fmt.Println("Unhandled error:", err)
|
||||||
}
|
}
|
||||||
|
timesChan <- responseTime
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,11 @@ func main() {
|
|||||||
passwordPtr := flag.String("password", "", "Redis user password")
|
passwordPtr := flag.String("password", "", "Redis user password")
|
||||||
//dbPtr := flag.Int("db", 0, "Redis db, default 0")
|
//dbPtr := flag.Int("db", 0, "Redis db, default 0")
|
||||||
initializeDBPtr := flag.Bool("initialize", false, "Boolean initialize db, default false")
|
initializeDBPtr := flag.Bool("initialize", false, "Boolean initialize db, default false")
|
||||||
ratePtr := flag.Int("rate", 5, "Test rate limit, default 50/sec")
|
ratePtr := flag.Int("rate", 50, "Test rate limit, default 30/sec")
|
||||||
burstPtr := flag.Bool("burst", false, "Boolean burst test default true")
|
burstPtr := flag.Bool("burst", true, "Boolean burst test default true")
|
||||||
//todo this should be off that same csv rather than an input
|
//todo this should be off that same csv rather than an input
|
||||||
maxEntriesPtr := flag.Int("dbEntries", 50000, "Test rate limit, default 50/sec")
|
maxEntriesPtr := flag.Int("dbEntries", 50000, "Test rate limit, default 50/sec")
|
||||||
testDurationPtr := flag.Int("duration", 10, "Duration of each test")
|
testDurationPtr := flag.Int("duration", 50, "Duration of each test")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
host := *hostPtr
|
host := *hostPtr
|
||||||
@ -46,7 +46,17 @@ func main() {
|
|||||||
if initializeDB {
|
if initializeDB {
|
||||||
buildTestData(&client, 50000)
|
buildTestData(&client, 50000)
|
||||||
}
|
}
|
||||||
|
client.Close()
|
||||||
|
//refreshing state for next test
|
||||||
|
pool = newPool(host, username, password)
|
||||||
|
client = pool.Get()
|
||||||
|
defer client.Close()
|
||||||
getRateTest(&client, rate, keyMaxValue, duration)
|
getRateTest(&client, rate, keyMaxValue, duration)
|
||||||
|
client.Close()
|
||||||
|
//refreshing state for next test
|
||||||
|
pool = newPool(host, username, password)
|
||||||
|
client = pool.Get()
|
||||||
|
defer client.Close()
|
||||||
if burst {
|
if burst {
|
||||||
getBurstTest(&client, rate, keyMaxValue, duration)
|
getBurstTest(&client, rate, keyMaxValue, duration)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,20 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/montanaflynn/stats"
|
import (
|
||||||
|
"github.com/montanaflynn/stats"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
intToFloat takes []int64 and converts it to []float64 for processing
|
||||||
|
*/
|
||||||
|
func intToFloat(times []int64) []float64 {
|
||||||
|
var floatArray []float64
|
||||||
|
for timeRange := range times {
|
||||||
|
floatArray = append(floatArray, float64(timeRange))
|
||||||
|
}
|
||||||
|
return floatArray
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getResponseTimes takes a list of ints and returns mean, stddev, 95p, 99p
|
getResponseTimes takes a list of ints and returns mean, stddev, 95p, 99p
|
||||||
@ -14,8 +28,16 @@ func getResponseTimes(times []float64) (float64, float64, float64, float64) {
|
|||||||
return mean, stddev, perc99, perc95
|
return mean, stddev, perc99, perc95
|
||||||
}
|
}
|
||||||
|
|
||||||
func keepTotal(timesChan chan float64, errorChan chan bool, endChan chan bool) ([]float64, int) {
|
/**
|
||||||
var timesSlice []float64
|
keepTotal takes several channels and keeps a running total of
|
||||||
|
duration and errors
|
||||||
|
*/
|
||||||
|
func keepTotal(timesChan chan time.Duration,
|
||||||
|
errorChan chan bool,
|
||||||
|
endChan chan bool,
|
||||||
|
totalTimeChan chan []int64,
|
||||||
|
totalErrorChan chan int) {
|
||||||
|
var timesSlice []int64
|
||||||
var errorRate int
|
var errorRate int
|
||||||
end := false
|
end := false
|
||||||
for {
|
for {
|
||||||
@ -24,14 +46,16 @@ func keepTotal(timesChan chan float64, errorChan chan bool, endChan chan bool) (
|
|||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
case timeValue := <-timesChan:
|
case timeValue := <-timesChan:
|
||||||
timesSlice = append(timesSlice, timeValue)
|
typedTimeValue := int64(1) * timeValue.Microseconds()
|
||||||
|
timesSlice = append(timesSlice, typedTimeValue)
|
||||||
case <-errorChan:
|
case <-errorChan:
|
||||||
errorRate++
|
errorRate += 1
|
||||||
case <-endChan:
|
case <-endChan:
|
||||||
if len(errorChan) == 0 && len(timesChan) == 0 {
|
if len(errorChan) == 0 && len(timesChan) == 0 {
|
||||||
end = true
|
end = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return timesSlice, errorRate
|
totalTimeChan <- timesSlice
|
||||||
|
totalErrorChan <- errorRate
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user