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  }