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