benchmark_server.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. *
  3. * Copyright 2016 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package main
  19. import (
  20. "flag"
  21. "fmt"
  22. "net"
  23. "runtime"
  24. "strconv"
  25. "strings"
  26. "sync"
  27. "time"
  28. "google.golang.org/grpc"
  29. "google.golang.org/grpc/benchmark"
  30. "google.golang.org/grpc/codes"
  31. "google.golang.org/grpc/credentials"
  32. "google.golang.org/grpc/internal/syscall"
  33. testpb "google.golang.org/grpc/interop/grpc_testing"
  34. "google.golang.org/grpc/status"
  35. "google.golang.org/grpc/testdata"
  36. )
  37. var (
  38. certFile = flag.String("tls_cert_file", "", "The TLS cert file")
  39. keyFile = flag.String("tls_key_file", "", "The TLS key file")
  40. )
  41. type benchmarkServer struct {
  42. port int
  43. cores int
  44. closeFunc func()
  45. mu sync.RWMutex
  46. lastResetTime time.Time
  47. rusageLastReset *syscall.Rusage
  48. }
  49. func printServerConfig(config *testpb.ServerConfig) {
  50. // Some config options are ignored:
  51. // - server type:
  52. // will always start sync server
  53. // - async server threads
  54. // - core list
  55. logger.Infof(" * server type: %v (ignored, always starts sync server)", config.ServerType)
  56. logger.Infof(" * async server threads: %v (ignored)", config.AsyncServerThreads)
  57. // TODO: use cores specified by CoreList when setting list of cores is supported in go.
  58. logger.Infof(" * core list: %v (ignored)", config.CoreList)
  59. logger.Infof(" - security params: %v", config.SecurityParams)
  60. logger.Infof(" - core limit: %v", config.CoreLimit)
  61. logger.Infof(" - port: %v", config.Port)
  62. logger.Infof(" - payload config: %v", config.PayloadConfig)
  63. }
  64. func startBenchmarkServer(config *testpb.ServerConfig, serverPort int) (*benchmarkServer, error) {
  65. printServerConfig(config)
  66. // Use all cpu cores available on machine by default.
  67. // TODO: Revisit this for the optimal default setup.
  68. numOfCores := runtime.NumCPU()
  69. if config.CoreLimit > 0 {
  70. numOfCores = int(config.CoreLimit)
  71. }
  72. runtime.GOMAXPROCS(numOfCores)
  73. var opts []grpc.ServerOption
  74. // Sanity check for server type.
  75. switch config.ServerType {
  76. case testpb.ServerType_SYNC_SERVER:
  77. case testpb.ServerType_ASYNC_SERVER:
  78. case testpb.ServerType_ASYNC_GENERIC_SERVER:
  79. default:
  80. return nil, status.Errorf(codes.InvalidArgument, "unknown server type: %v", config.ServerType)
  81. }
  82. // Set security options.
  83. if config.SecurityParams != nil {
  84. if *certFile == "" {
  85. *certFile = testdata.Path("server1.pem")
  86. }
  87. if *keyFile == "" {
  88. *keyFile = testdata.Path("server1.key")
  89. }
  90. creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)
  91. if err != nil {
  92. logger.Fatalf("failed to generate credentials: %v", err)
  93. }
  94. opts = append(opts, grpc.Creds(creds))
  95. }
  96. // Priority: config.Port > serverPort > default (0).
  97. port := int(config.Port)
  98. if port == 0 {
  99. port = serverPort
  100. }
  101. lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
  102. if err != nil {
  103. logger.Fatalf("Failed to listen: %v", err)
  104. }
  105. addr := lis.Addr().String()
  106. // Create different benchmark server according to config.
  107. var closeFunc func()
  108. if config.PayloadConfig != nil {
  109. switch payload := config.PayloadConfig.Payload.(type) {
  110. case *testpb.PayloadConfig_BytebufParams:
  111. opts = append(opts, grpc.CustomCodec(byteBufCodec{}))
  112. closeFunc = benchmark.StartServer(benchmark.ServerInfo{
  113. Type: "bytebuf",
  114. Metadata: payload.BytebufParams.RespSize,
  115. Listener: lis,
  116. }, opts...)
  117. case *testpb.PayloadConfig_SimpleParams:
  118. closeFunc = benchmark.StartServer(benchmark.ServerInfo{
  119. Type: "protobuf",
  120. Listener: lis,
  121. }, opts...)
  122. case *testpb.PayloadConfig_ComplexParams:
  123. return nil, status.Errorf(codes.Unimplemented, "unsupported payload config: %v", config.PayloadConfig)
  124. default:
  125. return nil, status.Errorf(codes.InvalidArgument, "unknown payload config: %v", config.PayloadConfig)
  126. }
  127. } else {
  128. // Start protobuf server if payload config is nil.
  129. closeFunc = benchmark.StartServer(benchmark.ServerInfo{
  130. Type: "protobuf",
  131. Listener: lis,
  132. }, opts...)
  133. }
  134. logger.Infof("benchmark server listening at %v", addr)
  135. addrSplitted := strings.Split(addr, ":")
  136. p, err := strconv.Atoi(addrSplitted[len(addrSplitted)-1])
  137. if err != nil {
  138. logger.Fatalf("failed to get port number from server address: %v", err)
  139. }
  140. return &benchmarkServer{
  141. port: p,
  142. cores: numOfCores,
  143. closeFunc: closeFunc,
  144. lastResetTime: time.Now(),
  145. rusageLastReset: syscall.GetRusage(),
  146. }, nil
  147. }
  148. // getStats returns the stats for benchmark server.
  149. // It resets lastResetTime if argument reset is true.
  150. func (bs *benchmarkServer) getStats(reset bool) *testpb.ServerStats {
  151. bs.mu.RLock()
  152. defer bs.mu.RUnlock()
  153. wallTimeElapsed := time.Since(bs.lastResetTime).Seconds()
  154. rusageLatest := syscall.GetRusage()
  155. uTimeElapsed, sTimeElapsed := syscall.CPUTimeDiff(bs.rusageLastReset, rusageLatest)
  156. if reset {
  157. bs.lastResetTime = time.Now()
  158. bs.rusageLastReset = rusageLatest
  159. }
  160. return &testpb.ServerStats{
  161. TimeElapsed: wallTimeElapsed,
  162. TimeUser: uTimeElapsed,
  163. TimeSystem: sTimeElapsed,
  164. }
  165. }