3 * Copyright 2016 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
30 "google.golang.org/grpc"
31 "google.golang.org/grpc/benchmark"
32 testpb "google.golang.org/grpc/benchmark/grpc_testing"
33 "google.golang.org/grpc/codes"
34 "google.golang.org/grpc/credentials"
35 "google.golang.org/grpc/grpclog"
36 "google.golang.org/grpc/testdata"
40 certFile = flag.String("tls_cert_file", "", "The TLS cert file")
41 keyFile = flag.String("tls_key_file", "", "The TLS key file")
44 type benchmarkServer struct {
49 lastResetTime time.Time
50 rusageLastReset *syscall.Rusage
53 func printServerConfig(config *testpb.ServerConfig) {
54 // Some config options are ignored:
56 // will always start sync server
57 // - async server threads
59 grpclog.Printf(" * server type: %v (ignored, always starts sync server)", config.ServerType)
60 grpclog.Printf(" * async server threads: %v (ignored)", config.AsyncServerThreads)
61 // TODO: use cores specified by CoreList when setting list of cores is supported in go.
62 grpclog.Printf(" * core list: %v (ignored)", config.CoreList)
64 grpclog.Printf(" - security params: %v", config.SecurityParams)
65 grpclog.Printf(" - core limit: %v", config.CoreLimit)
66 grpclog.Printf(" - port: %v", config.Port)
67 grpclog.Printf(" - payload config: %v", config.PayloadConfig)
70 func startBenchmarkServer(config *testpb.ServerConfig, serverPort int) (*benchmarkServer, error) {
71 printServerConfig(config)
73 // Use all cpu cores available on machine by default.
74 // TODO: Revisit this for the optimal default setup.
75 numOfCores := runtime.NumCPU()
76 if config.CoreLimit > 0 {
77 numOfCores = int(config.CoreLimit)
79 runtime.GOMAXPROCS(numOfCores)
81 var opts []grpc.ServerOption
83 // Sanity check for server type.
84 switch config.ServerType {
85 case testpb.ServerType_SYNC_SERVER:
86 case testpb.ServerType_ASYNC_SERVER:
87 case testpb.ServerType_ASYNC_GENERIC_SERVER:
89 return nil, grpc.Errorf(codes.InvalidArgument, "unknow server type: %v", config.ServerType)
92 // Set security options.
93 if config.SecurityParams != nil {
95 *certFile = testdata.Path("server1.pem")
98 *keyFile = testdata.Path("server1.key")
100 creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)
102 grpclog.Fatalf("failed to generate credentials %v", err)
104 opts = append(opts, grpc.Creds(creds))
107 // Priority: config.Port > serverPort > default (0).
108 port := int(config.Port)
113 // Create different benchmark server according to config.
119 if config.PayloadConfig != nil {
120 switch payload := config.PayloadConfig.Payload.(type) {
121 case *testpb.PayloadConfig_BytebufParams:
122 opts = append(opts, grpc.CustomCodec(byteBufCodec{}))
123 addr, closeFunc = benchmark.StartServer(benchmark.ServerInfo{
124 Addr: ":" + strconv.Itoa(port),
126 Metadata: payload.BytebufParams.RespSize,
128 case *testpb.PayloadConfig_SimpleParams:
129 addr, closeFunc = benchmark.StartServer(benchmark.ServerInfo{
130 Addr: ":" + strconv.Itoa(port),
133 case *testpb.PayloadConfig_ComplexParams:
134 return nil, grpc.Errorf(codes.Unimplemented, "unsupported payload config: %v", config.PayloadConfig)
136 return nil, grpc.Errorf(codes.InvalidArgument, "unknow payload config: %v", config.PayloadConfig)
139 // Start protobuf server if payload config is nil.
140 addr, closeFunc = benchmark.StartServer(benchmark.ServerInfo{
141 Addr: ":" + strconv.Itoa(port),
146 grpclog.Printf("benchmark server listening at %v", addr)
147 addrSplitted := strings.Split(addr, ":")
148 p, err := strconv.Atoi(addrSplitted[len(addrSplitted)-1])
150 grpclog.Fatalf("failed to get port number from server address: %v", err)
153 rusage := new(syscall.Rusage)
154 syscall.Getrusage(syscall.RUSAGE_SELF, rusage)
156 return &benchmarkServer{
159 closeFunc: closeFunc,
160 lastResetTime: time.Now(),
161 rusageLastReset: rusage,
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 {
169 defer bs.mu.RUnlock()
170 wallTimeElapsed := time.Since(bs.lastResetTime).Seconds()
171 rusageLatest := new(syscall.Rusage)
172 syscall.Getrusage(syscall.RUSAGE_SELF, rusageLatest)
173 uTimeElapsed, sTimeElapsed := cpuTimeDiff(bs.rusageLastReset, rusageLatest)
176 bs.lastResetTime = time.Now()
177 bs.rusageLastReset = rusageLatest
179 return &testpb.ServerStats{
180 TimeElapsed: wallTimeElapsed,
181 TimeUser: uTimeElapsed,
182 TimeSystem: sTimeElapsed,