diff --git a/Makefile b/Makefile index 03d8959e..42c86f28 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,10 @@ all: testdeps testdeps: testdata/redis/src/redis-server -.PHONY: all test testdeps +bench: testdeps + go test ./... -test.run=NONE -test.bench=. -test.benchmem + +.PHONY: all test testdeps bench testdata/redis: mkdir -p $@ diff --git a/bench_test.go b/bench_test.go index f4cffc1d..6a7edd62 100644 --- a/bench_test.go +++ b/bench_test.go @@ -2,15 +2,12 @@ package redis_test import ( "bytes" - "errors" - "net" "testing" "time" redigo "github.com/garyburd/redigo/redis" "gopkg.in/redis.v3" - "gopkg.in/redis.v3/internal/pool" ) func benchmarkRedisClient(poolSize int) *redis.Client { @@ -276,70 +273,3 @@ func BenchmarkZAdd(b *testing.B) { } }) } - -func benchmarkPoolGetPut(b *testing.B, poolSize int) { - dial := func() (net.Conn, error) { - return &net.TCPConn{}, nil - } - pool := pool.NewConnPool(dial, poolSize, time.Second, 0) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - conn, _, err := pool.Get() - if err != nil { - b.Fatalf("no error expected on pool.Get but received: %s", err.Error()) - } - if err = pool.Put(conn); err != nil { - b.Fatalf("no error expected on pool.Put but received: %s", err.Error()) - } - } - }) -} - -func BenchmarkPoolGetPut10Conns(b *testing.B) { - benchmarkPoolGetPut(b, 10) -} - -func BenchmarkPoolGetPut100Conns(b *testing.B) { - benchmarkPoolGetPut(b, 100) -} - -func BenchmarkPoolGetPut1000Conns(b *testing.B) { - benchmarkPoolGetPut(b, 1000) -} - -func benchmarkPoolGetRemove(b *testing.B, poolSize int) { - dial := func() (net.Conn, error) { - return &net.TCPConn{}, nil - } - pool := pool.NewConnPool(dial, poolSize, time.Second, 0) - removeReason := errors.New("benchmark") - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - conn, _, err := pool.Get() - if err != nil { - b.Fatalf("no error expected on pool.Get but received: %s", err.Error()) - } - if err = pool.Replace(conn, removeReason); err != nil { - b.Fatalf("no error expected on pool.Remove but received: %s", err.Error()) - } - } - }) -} - -func BenchmarkPoolGetRemove10Conns(b *testing.B) { - benchmarkPoolGetRemove(b, 10) -} - -func BenchmarkPoolGetRemove100Conns(b *testing.B) { - benchmarkPoolGetRemove(b, 100) -} - -func BenchmarkPoolGetRemove1000Conns(b *testing.B) { - benchmarkPoolGetRemove(b, 1000) -} diff --git a/internal/pool/bench_test.go b/internal/pool/bench_test.go new file mode 100644 index 00000000..ba6df0c0 --- /dev/null +++ b/internal/pool/bench_test.go @@ -0,0 +1,80 @@ +package pool_test + +import ( + "errors" + "net" + "testing" + "time" + + "gopkg.in/redis.v3/internal/pool" +) + +func benchmarkPoolGetPut(b *testing.B, poolSize int) { + dial := func() (net.Conn, error) { + return &net.TCPConn{}, nil + } + pool := pool.NewConnPool(dial, poolSize, time.Second, 0) + pool.DialLimiter = nil + + b.ResetTimer() + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + conn, _, err := pool.Get() + if err != nil { + b.Fatalf("no error expected on pool.Get but received: %s", err.Error()) + } + if err = pool.Put(conn); err != nil { + b.Fatalf("no error expected on pool.Put but received: %s", err.Error()) + } + } + }) +} + +func BenchmarkPoolGetPut10Conns(b *testing.B) { + benchmarkPoolGetPut(b, 10) +} + +func BenchmarkPoolGetPut100Conns(b *testing.B) { + benchmarkPoolGetPut(b, 100) +} + +func BenchmarkPoolGetPut1000Conns(b *testing.B) { + benchmarkPoolGetPut(b, 1000) +} + +func benchmarkPoolGetReplace(b *testing.B, poolSize int) { + dial := func() (net.Conn, error) { + return &net.TCPConn{}, nil + } + pool := pool.NewConnPool(dial, poolSize, time.Second, 0) + pool.DialLimiter = nil + + removeReason := errors.New("benchmark") + + b.ResetTimer() + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + conn, _, err := pool.Get() + if err != nil { + b.Fatalf("no error expected on pool.Get but received: %s", err.Error()) + } + if err = pool.Replace(conn, removeReason); err != nil { + b.Fatalf("no error expected on pool.Remove but received: %s", err.Error()) + } + } + }) +} + +func BenchmarkPoolGetReplace10Conns(b *testing.B) { + benchmarkPoolGetReplace(b, 10) +} + +func BenchmarkPoolGetReplace100Conns(b *testing.B) { + benchmarkPoolGetReplace(b, 100) +} + +func BenchmarkPoolGetReplace1000Conns(b *testing.B) { + benchmarkPoolGetReplace(b, 1000) +} diff --git a/internal/pool/pool.go b/internal/pool/pool.go index bed6b468..60b9c402 100644 --- a/internal/pool/pool.go +++ b/internal/pool/pool.go @@ -43,12 +43,12 @@ type Pooler interface { type dialer func() (net.Conn, error) type ConnPool struct { - _dial dialer + _dial dialer + DialLimiter *ratelimit.RateLimiter poolTimeout time.Duration idleTimeout time.Duration - rl *ratelimit.RateLimiter conns *connList freeConns chan *Conn stats PoolStats @@ -60,12 +60,12 @@ type ConnPool struct { func NewConnPool(dial dialer, poolSize int, poolTimeout, idleTimeout time.Duration) *ConnPool { p := &ConnPool{ - _dial: dial, + _dial: dial, + DialLimiter: ratelimit.New(3*poolSize, time.Second), poolTimeout: poolTimeout, idleTimeout: idleTimeout, - rl: ratelimit.New(3*poolSize, time.Second), conns: newConnList(poolSize), freeConns: make(chan *Conn, poolSize), } @@ -128,7 +128,7 @@ func (p *ConnPool) wait() *Conn { } func (p *ConnPool) dial() (net.Conn, error) { - if p.rl.Limit() { + if p.DialLimiter != nil && p.DialLimiter.Limit() { err := fmt.Errorf( "redis: you open connections too fast (last_error=%q)", p.loadLastErr(),