github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/benchmark/worker/main.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 // Binary worker implements the benchmark worker that can turn into a benchmark 20 // client or server. 21 package main 22 23 import ( 24 "context" 25 "flag" 26 "fmt" 27 "io" 28 "net" 29 "runtime" 30 "strconv" 31 "time" 32 33 _ "github.com/hxx258456/ccgo/gmhttp/pprof" 34 35 http "github.com/hxx258456/ccgo/gmhttp" 36 37 grpc "github.com/hxx258456/ccgo/grpc" 38 "github.com/hxx258456/ccgo/grpc/codes" 39 "github.com/hxx258456/ccgo/grpc/grpclog" 40 "github.com/hxx258456/ccgo/grpc/status" 41 42 testgrpc "github.com/hxx258456/ccgo/grpc/interop/grpc_testing" 43 testpb "github.com/hxx258456/ccgo/grpc/interop/grpc_testing" 44 ) 45 46 var ( 47 driverPort = flag.Int("driver_port", 10000, "port for communication with driver") 48 serverPort = flag.Int("server_port", 0, "port for benchmark server if not specified by server config message") 49 pprofPort = flag.Int("pprof_port", -1, "Port for pprof debug server to listen on. Pprof server doesn't start if unset") 50 blockProfRate = flag.Int("block_prof_rate", 0, "fraction of goroutine blocking events to report in blocking profile") 51 52 logger = grpclog.Component("benchmark") 53 ) 54 55 type byteBufCodec struct { 56 } 57 58 func (byteBufCodec) Marshal(v interface{}) ([]byte, error) { 59 b, ok := v.(*[]byte) 60 if !ok { 61 return nil, fmt.Errorf("failed to marshal: %v is not type of *[]byte", v) 62 } 63 return *b, nil 64 } 65 66 func (byteBufCodec) Unmarshal(data []byte, v interface{}) error { 67 b, ok := v.(*[]byte) 68 if !ok { 69 return fmt.Errorf("failed to marshal: %v is not type of *[]byte", v) 70 } 71 *b = data 72 return nil 73 } 74 75 func (byteBufCodec) String() string { 76 return "bytebuffer" 77 } 78 79 // workerServer implements WorkerService rpc handlers. 80 // It can create benchmarkServer or benchmarkClient on demand. 81 type workerServer struct { 82 testgrpc.UnimplementedWorkerServiceServer 83 stop chan<- bool 84 serverPort int 85 } 86 87 func (s *workerServer) RunServer(stream testgrpc.WorkerService_RunServerServer) error { 88 var bs *benchmarkServer 89 defer func() { 90 // Close benchmark server when stream ends. 91 logger.Infof("closing benchmark server") 92 if bs != nil { 93 bs.closeFunc() 94 } 95 }() 96 for { 97 in, err := stream.Recv() 98 if err == io.EOF { 99 return nil 100 } 101 if err != nil { 102 return err 103 } 104 105 var out *testpb.ServerStatus 106 switch argtype := in.Argtype.(type) { 107 case *testpb.ServerArgs_Setup: 108 logger.Infof("server setup received:") 109 if bs != nil { 110 logger.Infof("server setup received when server already exists, closing the existing server") 111 bs.closeFunc() 112 } 113 bs, err = startBenchmarkServer(argtype.Setup, s.serverPort) 114 if err != nil { 115 return err 116 } 117 out = &testpb.ServerStatus{ 118 Stats: bs.getStats(false), 119 Port: int32(bs.port), 120 Cores: int32(bs.cores), 121 } 122 123 case *testpb.ServerArgs_Mark: 124 logger.Infof("server mark received:") 125 logger.Infof(" - %v", argtype) 126 if bs == nil { 127 return status.Error(codes.InvalidArgument, "server does not exist when mark received") 128 } 129 out = &testpb.ServerStatus{ 130 Stats: bs.getStats(argtype.Mark.Reset_), 131 Port: int32(bs.port), 132 Cores: int32(bs.cores), 133 } 134 } 135 136 if err := stream.Send(out); err != nil { 137 return err 138 } 139 } 140 } 141 142 func (s *workerServer) RunClient(stream testgrpc.WorkerService_RunClientServer) error { 143 var bc *benchmarkClient 144 defer func() { 145 // Shut down benchmark client when stream ends. 146 logger.Infof("shuting down benchmark client") 147 if bc != nil { 148 bc.shutdown() 149 } 150 }() 151 for { 152 in, err := stream.Recv() 153 if err == io.EOF { 154 return nil 155 } 156 if err != nil { 157 return err 158 } 159 160 var out *testpb.ClientStatus 161 switch t := in.Argtype.(type) { 162 case *testpb.ClientArgs_Setup: 163 logger.Infof("client setup received:") 164 if bc != nil { 165 logger.Infof("client setup received when client already exists, shuting down the existing client") 166 bc.shutdown() 167 } 168 bc, err = startBenchmarkClient(t.Setup) 169 if err != nil { 170 return err 171 } 172 out = &testpb.ClientStatus{ 173 Stats: bc.getStats(false), 174 } 175 176 case *testpb.ClientArgs_Mark: 177 logger.Infof("client mark received:") 178 logger.Infof(" - %v", t) 179 if bc == nil { 180 return status.Error(codes.InvalidArgument, "client does not exist when mark received") 181 } 182 out = &testpb.ClientStatus{ 183 Stats: bc.getStats(t.Mark.Reset_), 184 } 185 } 186 187 if err := stream.Send(out); err != nil { 188 return err 189 } 190 } 191 } 192 193 func (s *workerServer) CoreCount(ctx context.Context, in *testpb.CoreRequest) (*testpb.CoreResponse, error) { 194 logger.Infof("core count: %v", runtime.NumCPU()) 195 return &testpb.CoreResponse{Cores: int32(runtime.NumCPU())}, nil 196 } 197 198 func (s *workerServer) QuitWorker(ctx context.Context, in *testpb.Void) (*testpb.Void, error) { 199 logger.Infof("quitting worker") 200 s.stop <- true 201 return &testpb.Void{}, nil 202 } 203 204 func main() { 205 grpc.EnableTracing = false 206 207 flag.Parse() 208 lis, err := net.Listen("tcp", ":"+strconv.Itoa(*driverPort)) 209 if err != nil { 210 logger.Fatalf("failed to listen: %v", err) 211 } 212 logger.Infof("worker listening at port %v", *driverPort) 213 214 s := grpc.NewServer() 215 stop := make(chan bool) 216 testgrpc.RegisterWorkerServiceServer(s, &workerServer{ 217 stop: stop, 218 serverPort: *serverPort, 219 }) 220 221 go func() { 222 <-stop 223 // Wait for 1 second before stopping the server to make sure the return value of QuitWorker is sent to client. 224 // TODO revise this once server graceful stop is supported in gRPC. 225 time.Sleep(time.Second) 226 s.Stop() 227 }() 228 229 runtime.SetBlockProfileRate(*blockProfRate) 230 231 if *pprofPort >= 0 { 232 go func() { 233 logger.Infoln("Starting pprof server on port " + strconv.Itoa(*pprofPort)) 234 logger.Infoln(http.ListenAndServe("localhost:"+strconv.Itoa(*pprofPort), nil)) 235 }() 236 } 237 238 s.Serve(lis) 239 }