client.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. package main
  2. import (
  3. "flag"
  4. "log"
  5. "reflect"
  6. "sync"
  7. "sync/atomic"
  8. "time"
  9. "go-common/library/net/netutil/breaker"
  10. "go-common/library/net/rpc/warden"
  11. "go-common/library/net/rpc/warden/benchmark/bench/proto"
  12. xtime "go-common/library/time"
  13. goproto "github.com/gogo/protobuf/proto"
  14. "github.com/montanaflynn/stats"
  15. "golang.org/x/net/context"
  16. "google.golang.org/grpc"
  17. )
  18. const (
  19. iws = 65535 * 1000
  20. iwsc = 65535 * 10000
  21. readBuffer = 32 * 1024
  22. writeBuffer = 32 * 1024
  23. )
  24. var concurrency = flag.Int("c", 50, "concurrency")
  25. var total = flag.Int("t", 500000, "total requests for all clients")
  26. var host = flag.String("s", "127.0.0.1:8972", "server ip and port")
  27. var isWarden = flag.Bool("w", true, "is warden or grpc client")
  28. var strLen = flag.Int("l", 600, "the length of the str")
  29. func wardenCli() proto.HelloClient {
  30. log.Println("start warden cli")
  31. client := warden.NewClient(&warden.ClientConfig{
  32. Dial: xtime.Duration(time.Second * 10),
  33. Timeout: xtime.Duration(time.Second * 10),
  34. Breaker: &breaker.Config{
  35. Window: xtime.Duration(3 * time.Second),
  36. Sleep: xtime.Duration(3 * time.Second),
  37. Bucket: 10,
  38. Ratio: 0.3,
  39. Request: 20,
  40. },
  41. },
  42. grpc.WithInitialWindowSize(iws),
  43. grpc.WithInitialConnWindowSize(iwsc),
  44. grpc.WithReadBufferSize(readBuffer),
  45. grpc.WithWriteBufferSize(writeBuffer))
  46. conn, err := client.Dial(context.Background(), *host)
  47. if err != nil {
  48. log.Fatalf("did not connect: %v", err)
  49. }
  50. cli := proto.NewHelloClient(conn)
  51. return cli
  52. }
  53. func grpcCli() proto.HelloClient {
  54. log.Println("start grpc cli")
  55. conn, err := grpc.Dial(*host, grpc.WithInsecure(),
  56. grpc.WithInitialWindowSize(iws),
  57. grpc.WithInitialConnWindowSize(iwsc),
  58. grpc.WithReadBufferSize(readBuffer),
  59. grpc.WithWriteBufferSize(writeBuffer))
  60. if err != nil {
  61. log.Fatalf("did not connect: %v", err)
  62. }
  63. cli := proto.NewHelloClient(conn)
  64. return cli
  65. }
  66. func main() {
  67. flag.Parse()
  68. c := *concurrency
  69. m := *total / c
  70. var wg sync.WaitGroup
  71. wg.Add(c)
  72. log.Printf("concurrency: %d\nrequests per client: %d\n\n", c, m)
  73. args := prepareArgs()
  74. b, _ := goproto.Marshal(args)
  75. log.Printf("message size: %d bytes\n\n", len(b))
  76. var trans uint64
  77. var transOK uint64
  78. d := make([][]int64, c)
  79. for i := 0; i < c; i++ {
  80. dt := make([]int64, 0, m)
  81. d = append(d, dt)
  82. }
  83. var cli proto.HelloClient
  84. if *isWarden {
  85. cli = wardenCli()
  86. } else {
  87. cli = grpcCli()
  88. }
  89. //warmup
  90. cli.Say(context.Background(), args)
  91. totalT := time.Now().UnixNano()
  92. for i := 0; i < c; i++ {
  93. go func(i int) {
  94. for j := 0; j < m; j++ {
  95. t := time.Now().UnixNano()
  96. reply, err := cli.Say(context.Background(), args)
  97. t = time.Now().UnixNano() - t
  98. d[i] = append(d[i], t)
  99. if err == nil && reply.Field1 == "OK" {
  100. atomic.AddUint64(&transOK, 1)
  101. }
  102. atomic.AddUint64(&trans, 1)
  103. }
  104. wg.Done()
  105. }(i)
  106. }
  107. wg.Wait()
  108. totalT = time.Now().UnixNano() - totalT
  109. totalT = totalT / 1e6
  110. log.Printf("took %d ms for %d requests\n", totalT, *total)
  111. totalD := make([]int64, 0, *total)
  112. for _, k := range d {
  113. totalD = append(totalD, k...)
  114. }
  115. totalD2 := make([]float64, 0, *total)
  116. for _, k := range totalD {
  117. totalD2 = append(totalD2, float64(k))
  118. }
  119. mean, _ := stats.Mean(totalD2)
  120. median, _ := stats.Median(totalD2)
  121. max, _ := stats.Max(totalD2)
  122. min, _ := stats.Min(totalD2)
  123. tp99, _ := stats.Percentile(totalD2, 99)
  124. tp999, _ := stats.Percentile(totalD2, 99.9)
  125. log.Printf("sent requests : %d\n", *total)
  126. log.Printf("received requests_OK : %d\n", atomic.LoadUint64(&transOK))
  127. log.Printf("throughput (TPS) : %d\n", int64(c*m)*1000/totalT)
  128. log.Printf("mean: %v ms, median: %v ms, max: %v ms, min: %v ms, p99: %v ms, p999:%v ms\n", mean/1e6, median/1e6, max/1e6, min/1e6, tp99/1e6, tp999/1e6)
  129. }
  130. func prepareArgs() *proto.BenchmarkMessage {
  131. b := true
  132. var i int32 = 120000
  133. var i64 int64 = 98765432101234
  134. var s = "许多往事在眼前一幕一幕,变的那麼模糊"
  135. repeat := *strLen / (8 * 54)
  136. if repeat == 0 {
  137. repeat = 1
  138. }
  139. var str string
  140. for i := 0; i < repeat; i++ {
  141. str += s
  142. }
  143. var args proto.BenchmarkMessage
  144. v := reflect.ValueOf(&args).Elem()
  145. num := v.NumField()
  146. for k := 0; k < num; k++ {
  147. field := v.Field(k)
  148. if field.Type().Kind() == reflect.Ptr {
  149. switch v.Field(k).Type().Elem().Kind() {
  150. case reflect.Int, reflect.Int32:
  151. field.Set(reflect.ValueOf(&i))
  152. case reflect.Int64:
  153. field.Set(reflect.ValueOf(&i64))
  154. case reflect.Bool:
  155. field.Set(reflect.ValueOf(&b))
  156. case reflect.String:
  157. field.Set(reflect.ValueOf(&str))
  158. }
  159. } else {
  160. switch field.Kind() {
  161. case reflect.Int, reflect.Int32, reflect.Int64:
  162. field.SetInt(9876543)
  163. case reflect.Bool:
  164. field.SetBool(true)
  165. case reflect.String:
  166. field.SetString(str)
  167. }
  168. }
  169. }
  170. return &args
  171. }