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.
 
 
 

185 line
5.4 KiB

  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. testpb "google.golang.org/grpc/benchmark/grpc_testing"
  31. "google.golang.org/grpc/codes"
  32. "google.golang.org/grpc/credentials"
  33. "google.golang.org/grpc/grpclog"
  34. "google.golang.org/grpc/internal/syscall"
  35. "google.golang.org/grpc/status"
  36. "google.golang.org/grpc/testdata"
  37. )
  38. var (
  39. certFile = flag.String("tls_cert_file", "", "The TLS cert file")
  40. keyFile = flag.String("tls_key_file", "", "The TLS key file")
  41. )
  42. type benchmarkServer struct {
  43. port int
  44. cores int
  45. closeFunc func()
  46. mu sync.RWMutex
  47. lastResetTime time.Time
  48. rusageLastReset *syscall.Rusage
  49. }
  50. func printServerConfig(config *testpb.ServerConfig) {
  51. // Some config options are ignored:
  52. // - server type:
  53. // will always start sync server
  54. // - async server threads
  55. // - core list
  56. grpclog.Infof(" * server type: %v (ignored, always starts sync server)", config.ServerType)
  57. grpclog.Infof(" * async server threads: %v (ignored)", config.AsyncServerThreads)
  58. // TODO: use cores specified by CoreList when setting list of cores is supported in go.
  59. grpclog.Infof(" * core list: %v (ignored)", config.CoreList)
  60. grpclog.Infof(" - security params: %v", config.SecurityParams)
  61. grpclog.Infof(" - core limit: %v", config.CoreLimit)
  62. grpclog.Infof(" - port: %v", config.Port)
  63. grpclog.Infof(" - payload config: %v", config.PayloadConfig)
  64. }
  65. func startBenchmarkServer(config *testpb.ServerConfig, serverPort int) (*benchmarkServer, error) {
  66. printServerConfig(config)
  67. // Use all cpu cores available on machine by default.
  68. // TODO: Revisit this for the optimal default setup.
  69. numOfCores := runtime.NumCPU()
  70. if config.CoreLimit > 0 {
  71. numOfCores = int(config.CoreLimit)
  72. }
  73. runtime.GOMAXPROCS(numOfCores)
  74. var opts []grpc.ServerOption
  75. // Sanity check for server type.
  76. switch config.ServerType {
  77. case testpb.ServerType_SYNC_SERVER:
  78. case testpb.ServerType_ASYNC_SERVER:
  79. case testpb.ServerType_ASYNC_GENERIC_SERVER:
  80. default:
  81. return nil, status.Errorf(codes.InvalidArgument, "unknown server type: %v", config.ServerType)
  82. }
  83. // Set security options.
  84. if config.SecurityParams != nil {
  85. if *certFile == "" {
  86. *certFile = testdata.Path("server1.pem")
  87. }
  88. if *keyFile == "" {
  89. *keyFile = testdata.Path("server1.key")
  90. }
  91. creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)
  92. if err != nil {
  93. grpclog.Fatalf("failed to generate credentials %v", err)
  94. }
  95. opts = append(opts, grpc.Creds(creds))
  96. }
  97. // Priority: config.Port > serverPort > default (0).
  98. port := int(config.Port)
  99. if port == 0 {
  100. port = serverPort
  101. }
  102. lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
  103. if err != nil {
  104. grpclog.Fatalf("Failed to listen: %v", err)
  105. }
  106. addr := lis.Addr().String()
  107. // Create different benchmark server according to config.
  108. var closeFunc func()
  109. if config.PayloadConfig != nil {
  110. switch payload := config.PayloadConfig.Payload.(type) {
  111. case *testpb.PayloadConfig_BytebufParams:
  112. opts = append(opts, grpc.CustomCodec(byteBufCodec{}))
  113. closeFunc = benchmark.StartServer(benchmark.ServerInfo{
  114. Type: "bytebuf",
  115. Metadata: payload.BytebufParams.RespSize,
  116. Listener: lis,
  117. }, opts...)
  118. case *testpb.PayloadConfig_SimpleParams:
  119. closeFunc = benchmark.StartServer(benchmark.ServerInfo{
  120. Type: "protobuf",
  121. Listener: lis,
  122. }, opts...)
  123. case *testpb.PayloadConfig_ComplexParams:
  124. return nil, status.Errorf(codes.Unimplemented, "unsupported payload config: %v", config.PayloadConfig)
  125. default:
  126. return nil, status.Errorf(codes.InvalidArgument, "unknown payload config: %v", config.PayloadConfig)
  127. }
  128. } else {
  129. // Start protobuf server if payload config is nil.
  130. closeFunc = benchmark.StartServer(benchmark.ServerInfo{
  131. Type: "protobuf",
  132. Listener: lis,
  133. }, opts...)
  134. }
  135. grpclog.Infof("benchmark server listening at %v", addr)
  136. addrSplitted := strings.Split(addr, ":")
  137. p, err := strconv.Atoi(addrSplitted[len(addrSplitted)-1])
  138. if err != nil {
  139. grpclog.Fatalf("failed to get port number from server address: %v", err)
  140. }
  141. return &benchmarkServer{
  142. port: p,
  143. cores: numOfCores,
  144. closeFunc: closeFunc,
  145. lastResetTime: time.Now(),
  146. rusageLastReset: syscall.GetRusage(),
  147. }, nil
  148. }
  149. // getStats returns the stats for benchmark server.
  150. // It resets lastResetTime if argument reset is true.
  151. func (bs *benchmarkServer) getStats(reset bool) *testpb.ServerStats {
  152. bs.mu.RLock()
  153. defer bs.mu.RUnlock()
  154. wallTimeElapsed := time.Since(bs.lastResetTime).Seconds()
  155. rusageLatest := syscall.GetRusage()
  156. uTimeElapsed, sTimeElapsed := syscall.CPUTimeDiff(bs.rusageLastReset, rusageLatest)
  157. if reset {
  158. bs.lastResetTime = time.Now()
  159. bs.rusageLastReset = rusageLatest
  160. }
  161. return &testpb.ServerStats{
  162. TimeElapsed: wallTimeElapsed,
  163. TimeUser: uTimeElapsed,
  164. TimeSystem: sTimeElapsed,
  165. }
  166. }