You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

260 lines
4.7 KiB

  1. // Copyright 2014 Gary Burd
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  11. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. // License for the specific language governing permissions and limitations
  13. // under the License.
  14. package redisx_test
  15. import (
  16. "net/textproto"
  17. "sync"
  18. "testing"
  19. "github.com/garyburd/redigo/internal/redistest"
  20. "github.com/garyburd/redigo/redis"
  21. "github.com/garyburd/redigo/redisx"
  22. )
  23. func TestConnMux(t *testing.T) {
  24. c, err := redistest.Dial()
  25. if err != nil {
  26. t.Fatalf("error connection to database, %v", err)
  27. }
  28. m := redisx.NewConnMux(c)
  29. defer m.Close()
  30. c1 := m.Get()
  31. c2 := m.Get()
  32. c1.Send("ECHO", "hello")
  33. c2.Send("ECHO", "world")
  34. c1.Flush()
  35. c2.Flush()
  36. s, err := redis.String(c1.Receive())
  37. if err != nil {
  38. t.Fatal(err)
  39. }
  40. if s != "hello" {
  41. t.Fatalf("echo returned %q, want %q", s, "hello")
  42. }
  43. s, err = redis.String(c2.Receive())
  44. if err != nil {
  45. t.Fatal(err)
  46. }
  47. if s != "world" {
  48. t.Fatalf("echo returned %q, want %q", s, "world")
  49. }
  50. c1.Close()
  51. c2.Close()
  52. }
  53. func TestConnMuxClose(t *testing.T) {
  54. c, err := redistest.Dial()
  55. if err != nil {
  56. t.Fatalf("error connection to database, %v", err)
  57. }
  58. m := redisx.NewConnMux(c)
  59. defer m.Close()
  60. c1 := m.Get()
  61. c2 := m.Get()
  62. if err := c1.Send("ECHO", "hello"); err != nil {
  63. t.Fatal(err)
  64. }
  65. if err := c1.Close(); err != nil {
  66. t.Fatal(err)
  67. }
  68. if err := c2.Send("ECHO", "world"); err != nil {
  69. t.Fatal(err)
  70. }
  71. if err := c2.Flush(); err != nil {
  72. t.Fatal(err)
  73. }
  74. s, err := redis.String(c2.Receive())
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. if s != "world" {
  79. t.Fatalf("echo returned %q, want %q", s, "world")
  80. }
  81. c2.Close()
  82. }
  83. func BenchmarkConn(b *testing.B) {
  84. b.StopTimer()
  85. c, err := redistest.Dial()
  86. if err != nil {
  87. b.Fatalf("error connection to database, %v", err)
  88. }
  89. defer c.Close()
  90. b.StartTimer()
  91. for i := 0; i < b.N; i++ {
  92. if _, err := c.Do("PING"); err != nil {
  93. b.Fatal(err)
  94. }
  95. }
  96. }
  97. func BenchmarkConnMux(b *testing.B) {
  98. b.StopTimer()
  99. c, err := redistest.Dial()
  100. if err != nil {
  101. b.Fatalf("error connection to database, %v", err)
  102. }
  103. m := redisx.NewConnMux(c)
  104. defer m.Close()
  105. b.StartTimer()
  106. for i := 0; i < b.N; i++ {
  107. c := m.Get()
  108. if _, err := c.Do("PING"); err != nil {
  109. b.Fatal(err)
  110. }
  111. c.Close()
  112. }
  113. }
  114. func BenchmarkPool(b *testing.B) {
  115. b.StopTimer()
  116. p := redis.Pool{Dial: redistest.Dial, MaxIdle: 1}
  117. defer p.Close()
  118. // Fill the pool.
  119. c := p.Get()
  120. if err := c.Err(); err != nil {
  121. b.Fatal(err)
  122. }
  123. c.Close()
  124. b.StartTimer()
  125. for i := 0; i < b.N; i++ {
  126. c := p.Get()
  127. if _, err := c.Do("PING"); err != nil {
  128. b.Fatal(err)
  129. }
  130. c.Close()
  131. }
  132. }
  133. const numConcurrent = 10
  134. func BenchmarkConnMuxConcurrent(b *testing.B) {
  135. b.StopTimer()
  136. c, err := redistest.Dial()
  137. if err != nil {
  138. b.Fatalf("error connection to database, %v", err)
  139. }
  140. defer c.Close()
  141. m := redisx.NewConnMux(c)
  142. var wg sync.WaitGroup
  143. wg.Add(numConcurrent)
  144. b.StartTimer()
  145. for i := 0; i < numConcurrent; i++ {
  146. go func() {
  147. defer wg.Done()
  148. for i := 0; i < b.N; i++ {
  149. c := m.Get()
  150. if _, err := c.Do("PING"); err != nil {
  151. b.Fatal(err)
  152. }
  153. c.Close()
  154. }
  155. }()
  156. }
  157. wg.Wait()
  158. }
  159. func BenchmarkPoolConcurrent(b *testing.B) {
  160. b.StopTimer()
  161. p := redis.Pool{Dial: redistest.Dial, MaxIdle: numConcurrent}
  162. defer p.Close()
  163. // Fill the pool.
  164. conns := make([]redis.Conn, numConcurrent)
  165. for i := range conns {
  166. c := p.Get()
  167. if err := c.Err(); err != nil {
  168. b.Fatal(err)
  169. }
  170. conns[i] = c
  171. }
  172. for _, c := range conns {
  173. c.Close()
  174. }
  175. var wg sync.WaitGroup
  176. wg.Add(numConcurrent)
  177. b.StartTimer()
  178. for i := 0; i < numConcurrent; i++ {
  179. go func() {
  180. defer wg.Done()
  181. for i := 0; i < b.N; i++ {
  182. c := p.Get()
  183. if _, err := c.Do("PING"); err != nil {
  184. b.Fatal(err)
  185. }
  186. c.Close()
  187. }
  188. }()
  189. }
  190. wg.Wait()
  191. }
  192. func BenchmarkPipelineConcurrency(b *testing.B) {
  193. b.StopTimer()
  194. c, err := redistest.Dial()
  195. if err != nil {
  196. b.Fatalf("error connection to database, %v", err)
  197. }
  198. defer c.Close()
  199. var wg sync.WaitGroup
  200. wg.Add(numConcurrent)
  201. var pipeline textproto.Pipeline
  202. b.StartTimer()
  203. for i := 0; i < numConcurrent; i++ {
  204. go func() {
  205. defer wg.Done()
  206. for i := 0; i < b.N; i++ {
  207. id := pipeline.Next()
  208. pipeline.StartRequest(id)
  209. c.Send("PING")
  210. c.Flush()
  211. pipeline.EndRequest(id)
  212. pipeline.StartResponse(id)
  213. _, err := c.Receive()
  214. if err != nil {
  215. b.Fatal(err)
  216. }
  217. pipeline.EndResponse(id)
  218. }
  219. }()
  220. }
  221. wg.Wait()
  222. }