2014-05-13 04:49:05 +04:00
package main
import (
"flag"
"fmt"
2014-06-22 06:39:23 +04:00
"github.com/siddontang/ledisdb/client/go/ledis"
2014-05-13 04:49:05 +04:00
"math/rand"
2014-10-24 16:32:49 +04:00
"runtime"
2014-10-28 12:57:29 +03:00
"strings"
2014-05-13 04:49:05 +04:00
"sync"
2014-09-04 10:00:32 +04:00
"sync/atomic"
2014-05-13 04:49:05 +04:00
"time"
)
var ip = flag . String ( "ip" , "127.0.0.1" , "redis/ledis/ssdb server ip" )
2014-07-08 11:31:36 +04:00
var port = flag . Int ( "port" , 6380 , "redis/ledis/ssdb server port" )
2014-05-13 04:49:05 +04:00
var number = flag . Int ( "n" , 1000 , "request number" )
var clients = flag . Int ( "c" , 50 , "number of clients" )
2014-09-04 11:49:51 +04:00
var round = flag . Int ( "r" , 1 , "benchmark round number" )
2014-10-23 09:49:43 +04:00
var valueSize = flag . Int ( "vsize" , 100 , "kv value size" )
2014-10-28 12:57:29 +03:00
var tests = flag . String ( "t" , "" , "only run the comma separated list of tests, set,get,del,lpush,lrange,lpop,hset,hget,hdel,zadd,zincr,zrange,zrevrange,zdel" )
2014-05-13 04:49:05 +04:00
var wg sync . WaitGroup
2014-06-22 06:39:23 +04:00
var client * ledis . Client
2014-05-13 04:49:05 +04:00
var loop int = 0
2014-10-29 07:32:57 +03:00
func waitBench ( c * ledis . Conn , cmd string , args ... interface { } ) {
2014-10-28 18:23:30 +03:00
_ , err := c . Do ( strings . ToUpper ( cmd ) , args ... )
2014-09-04 13:51:43 +04:00
if err != nil {
2014-10-28 18:23:30 +03:00
fmt . Printf ( "do %s error %s\n" , cmd , err . Error ( ) )
2014-05-13 04:49:05 +04:00
}
2014-10-29 07:32:57 +03:00
2014-05-13 04:49:05 +04:00
}
2014-10-29 07:32:57 +03:00
func bench ( cmd string , f func ( c * ledis . Conn ) ) {
2014-05-13 04:49:05 +04:00
wg . Add ( * clients )
2014-10-24 09:01:13 +04:00
t1 := time . Now ( )
2014-05-13 04:49:05 +04:00
for i := 0 ; i < * clients ; i ++ {
2014-09-04 13:51:43 +04:00
go func ( ) {
2014-10-29 07:32:57 +03:00
c := client . Get ( )
2014-10-24 12:39:06 +04:00
for j := 0 ; j < loop ; j ++ {
2014-10-29 07:32:57 +03:00
f ( c )
2014-09-04 13:51:43 +04:00
}
2014-10-29 07:32:57 +03:00
c . Close ( )
2014-09-04 13:51:43 +04:00
wg . Done ( )
} ( )
2014-05-13 04:49:05 +04:00
}
wg . Wait ( )
2014-10-24 09:01:13 +04:00
t2 := time . Now ( )
2014-05-13 04:49:05 +04:00
2014-10-28 12:57:29 +03:00
d := t2 . Sub ( t1 )
fmt . Printf ( "%s: %s %0.3f micros/op, %0.2fop/s\n" ,
cmd ,
d . String ( ) ,
float64 ( d . Nanoseconds ( ) / 1e3 ) / float64 ( * number ) ,
float64 ( * number ) / d . Seconds ( ) )
2014-05-13 04:49:05 +04:00
}
2014-09-04 10:00:32 +04:00
var kvSetBase int64 = 0
var kvGetBase int64 = 0
var kvIncrBase int64 = 0
var kvDelBase int64 = 0
2014-05-13 04:49:05 +04:00
func benchSet ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-10-23 09:49:43 +04:00
value := make ( [ ] byte , * valueSize )
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & kvSetBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "SET" , n , value )
2014-05-13 04:49:05 +04:00
}
bench ( "set" , f )
}
func benchGet ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & kvGetBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "GET" , n )
2014-09-04 10:00:32 +04:00
}
bench ( "get" , f )
}
func benchRandGet ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-10-28 18:23:30 +03:00
n := rand . Int ( ) % * number
2014-10-29 07:32:57 +03:00
waitBench ( c , "GET" , n )
2014-05-13 04:49:05 +04:00
}
2014-09-04 13:17:47 +04:00
bench ( "randget" , f )
2014-05-13 04:49:05 +04:00
}
2014-09-04 10:00:32 +04:00
func benchDel ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & kvDelBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "DEL" , n )
2014-09-04 10:00:32 +04:00
}
bench ( "del" , f )
}
2014-05-13 04:49:05 +04:00
func benchPushList ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-10-23 09:49:43 +04:00
value := make ( [ ] byte , 100 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "RPUSH" , "mytestlist" , value )
2014-05-13 04:49:05 +04:00
}
bench ( "rpush" , f )
}
func benchRangeList10 ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "LRANGE" , "mytestlist" , 0 , 10 )
2014-05-13 04:49:05 +04:00
}
2014-09-04 13:17:47 +04:00
bench ( "lrange10" , f )
2014-05-13 04:49:05 +04:00
}
func benchRangeList50 ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "LRANGE" , "mytestlist" , 0 , 50 )
2014-05-13 04:49:05 +04:00
}
2014-09-04 13:17:47 +04:00
bench ( "lrange50" , f )
2014-05-13 04:49:05 +04:00
}
func benchRangeList100 ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "LRANGE" , "mytestlist" , 0 , 100 )
2014-05-13 04:49:05 +04:00
}
2014-09-04 13:17:47 +04:00
bench ( "lrange100" , f )
2014-05-13 04:49:05 +04:00
}
func benchPopList ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "LPOP" , "mytestlist" )
2014-05-13 04:49:05 +04:00
}
bench ( "lpop" , f )
}
2014-09-04 10:00:32 +04:00
var hashSetBase int64 = 0
var hashIncrBase int64 = 0
var hashGetBase int64 = 0
var hashDelBase int64 = 0
2014-05-13 04:49:05 +04:00
func benchHset ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 11:49:51 +04:00
value := make ( [ ] byte , 100 )
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & hashSetBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "HSET" , "myhashkey" , n , value )
2014-05-13 04:49:05 +04:00
}
bench ( "hset" , f )
}
func benchHGet ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & hashGetBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "HGET" , "myhashkey" , n )
2014-09-04 10:00:32 +04:00
}
bench ( "hget" , f )
}
func benchHRandGet ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-10-28 18:23:30 +03:00
n := rand . Int ( ) % * number
2014-10-29 07:32:57 +03:00
waitBench ( c , "HGET" , "myhashkey" , n )
2014-05-13 04:49:05 +04:00
}
2014-09-04 13:17:47 +04:00
bench ( "hrandget" , f )
2014-05-13 04:49:05 +04:00
}
func benchHDel ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & hashDelBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "HDEL" , "myhashkey" , n )
2014-05-13 04:49:05 +04:00
}
bench ( "hdel" , f )
}
2014-09-04 10:00:32 +04:00
var zsetAddBase int64 = 0
var zsetDelBase int64 = 0
var zsetIncrBase int64 = 0
2014-05-13 04:49:05 +04:00
func benchZAdd ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 11:49:51 +04:00
member := make ( [ ] byte , 16 )
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & zsetAddBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "ZADD" , "myzsetkey" , n , member )
2014-05-13 04:49:05 +04:00
}
bench ( "zadd" , f )
}
func benchZDel ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & zsetDelBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "ZREM" , "myzsetkey" , n )
2014-05-13 04:49:05 +04:00
}
bench ( "zrem" , f )
}
func benchZIncr ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
2014-09-04 10:00:32 +04:00
n := atomic . AddInt64 ( & zsetIncrBase , 1 )
2014-10-29 07:32:57 +03:00
waitBench ( c , "ZINCRBY" , "myzsetkey" , 1 , n )
2014-05-13 04:49:05 +04:00
}
bench ( "zincrby" , f )
}
func benchZRangeByScore ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "ZRANGEBYSCORE" , "myzsetkey" , 0 , rand . Int ( ) , "withscores" , "limit" , rand . Int ( ) % 100 , 100 )
2014-05-13 04:49:05 +04:00
}
bench ( "zrangebyscore" , f )
}
func benchZRangeByRank ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "ZRANGE" , "myzsetkey" , 0 , rand . Int ( ) % 100 )
2014-05-13 04:49:05 +04:00
}
bench ( "zrange" , f )
}
func benchZRevRangeByScore ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "ZREVRANGEBYSCORE" , "myzsetkey" , 0 , rand . Int ( ) , "withscores" , "limit" , rand . Int ( ) % 100 , 100 )
2014-05-13 04:49:05 +04:00
}
bench ( "zrevrangebyscore" , f )
}
func benchZRevRangeByRank ( ) {
2014-10-29 07:32:57 +03:00
f := func ( c * ledis . Conn ) {
waitBench ( c , "ZREVRANGE" , "myzsetkey" , 0 , rand . Int ( ) % 100 )
2014-05-13 04:49:05 +04:00
}
bench ( "zrevrange" , f )
}
func main ( ) {
2014-10-24 16:32:49 +04:00
runtime . GOMAXPROCS ( runtime . NumCPU ( ) )
2014-05-13 04:49:05 +04:00
flag . Parse ( )
if * number <= 0 {
panic ( "invalid number" )
return
}
if * clients <= 0 || * number < * clients {
panic ( "invalid client number" )
return
}
loop = * number / * clients
addr := fmt . Sprintf ( "%s:%d" , * ip , * port )
2014-06-22 06:39:23 +04:00
cfg := new ( ledis . Config )
cfg . Addr = addr
2014-09-04 13:51:43 +04:00
cfg . MaxIdleConns = * clients
2014-10-25 11:27:05 +04:00
cfg . ReadBufferSize = 10240
cfg . WriteBufferSize = 10240
2014-06-22 06:39:23 +04:00
client = ledis . NewClient ( cfg )
2014-05-13 04:49:05 +04:00
2014-10-29 07:32:57 +03:00
for i := 0 ; i < * clients ; i ++ {
c := client . Get ( )
c . Close ( )
}
2014-09-04 11:49:51 +04:00
if * round <= 0 {
* round = 1
2014-09-04 10:00:32 +04:00
}
2014-10-28 12:57:29 +03:00
runAll := true
ts := strings . Split ( * tests , "," )
if len ( ts ) > 0 && len ( ts [ 0 ] ) != 0 {
runAll = false
}
needTest := make ( map [ string ] struct { } )
for _ , s := range ts {
needTest [ strings . ToLower ( s ) ] = struct { } { }
}
checkTest := func ( cmd string ) bool {
if runAll {
return true
} else if _ , ok := needTest [ cmd ] ; ok {
return ok
}
return false
}
2014-09-04 11:49:51 +04:00
for i := 0 ; i < * round ; i ++ {
2014-10-28 12:57:29 +03:00
if checkTest ( "set" ) {
benchSet ( )
}
if checkTest ( "get" ) {
benchGet ( )
benchRandGet ( )
}
2014-10-08 11:19:50 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "del" ) {
2014-10-08 11:19:50 +04:00
benchDel ( )
}
2014-09-04 11:49:51 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "lpush" ) {
benchPushList ( )
}
if checkTest ( "lrange" ) {
benchRangeList10 ( )
benchRangeList50 ( )
benchRangeList100 ( )
}
2014-10-08 11:19:50 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "lpop" ) {
2014-10-08 11:19:50 +04:00
benchPopList ( )
}
2014-09-04 11:49:51 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "hset" ) {
benchHset ( )
}
if checkTest ( "hget" ) {
benchHGet ( )
benchHRandGet ( )
}
2014-10-08 11:19:50 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "hdel" ) {
2014-10-08 11:19:50 +04:00
benchHDel ( )
}
2014-09-04 11:49:51 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "zadd" ) {
benchZAdd ( )
}
if checkTest ( "zincr" ) {
benchZIncr ( )
}
if checkTest ( "zrange" ) {
benchZRangeByRank ( )
benchZRangeByScore ( )
}
2014-09-04 11:49:51 +04:00
2014-10-28 12:57:29 +03:00
if checkTest ( "zrevrange" ) {
//rev is too slow in leveldb, rocksdb or other
//maybe disable for huge data benchmark
2014-09-04 11:49:51 +04:00
benchZRevRangeByRank ( )
benchZRevRangeByScore ( )
}
2014-10-28 12:57:29 +03:00
if checkTest ( "zdel" ) {
2014-10-08 11:19:50 +04:00
benchZDel ( )
}
2014-09-04 11:49:51 +04:00
println ( "" )
}
2014-05-13 04:49:05 +04:00
}