1 #region Copyright notice and license 2 3 // Copyright 2015 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 #endregion 18 19 using System; 20 using System.Collections.Generic; 21 using System.Diagnostics; 22 using System.IO; 23 using System.Linq; 24 using System.Text.RegularExpressions; 25 using System.Threading; 26 using System.Threading.Tasks; 27 using Google.Protobuf; 28 using Grpc.Core; 29 using Grpc.Core.Logging; 30 using Grpc.Core.Utils; 31 using NUnit.Framework; 32 using Grpc.Testing; 33 34 namespace Grpc.IntegrationTesting 35 { 36 /// <summary> 37 /// Helper methods to start server runners for performance testing. 38 /// </summary> 39 public class ServerRunners 40 { 41 static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<ServerRunners>(); 42 43 /// <summary> 44 /// Creates a started server runner. 45 /// </summary> CreateStarted(ServerConfig config)46 public static IServerRunner CreateStarted(ServerConfig config) 47 { 48 Logger.Debug("ServerConfig: {0}", config); 49 var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure; 50 51 if (config.AsyncServerThreads != 0) 52 { 53 Logger.Warning("ServerConfig.AsyncServerThreads is not supported for C#. Ignoring the value"); 54 } 55 if (config.CoreLimit != 0) 56 { 57 Logger.Warning("ServerConfig.CoreLimit is not supported for C#. Ignoring the value"); 58 } 59 if (config.CoreList.Count > 0) 60 { 61 Logger.Warning("ServerConfig.CoreList is not supported for C#. Ignoring the value"); 62 } 63 64 ServerServiceDefinition service = null; 65 if (config.ServerType == ServerType.AsyncServer) 66 { 67 GrpcPreconditions.CheckArgument(config.PayloadConfig == null, 68 "ServerConfig.PayloadConfig shouldn't be set for BenchmarkService based server."); 69 service = BenchmarkService.BindService(new BenchmarkServiceImpl()); 70 } 71 else if (config.ServerType == ServerType.AsyncGenericServer) 72 { 73 var genericService = new GenericServiceImpl(config.PayloadConfig.BytebufParams.RespSize); 74 service = GenericService.BindHandler(genericService.StreamingCall); 75 } 76 else 77 { 78 throw new ArgumentException("Unsupported ServerType"); 79 } 80 81 var channelOptions = new List<ChannelOption>(config.ChannelArgs.Select((arg) => arg.ToChannelOption())); 82 var server = new Server(channelOptions) 83 { 84 Services = { service }, 85 Ports = { new ServerPort("[::]", config.Port, credentials) } 86 }; 87 88 server.Start(); 89 return new ServerRunnerImpl(server); 90 } 91 92 private class GenericServiceImpl 93 { 94 readonly byte[] response; 95 GenericServiceImpl(int responseSize)96 public GenericServiceImpl(int responseSize) 97 { 98 this.response = new byte[responseSize]; 99 } 100 101 /// <summary> 102 /// Generic streaming call handler. 103 /// </summary> StreamingCall(IAsyncStreamReader<byte[]> requestStream, IServerStreamWriter<byte[]> responseStream, ServerCallContext context)104 public async Task StreamingCall(IAsyncStreamReader<byte[]> requestStream, IServerStreamWriter<byte[]> responseStream, ServerCallContext context) 105 { 106 await requestStream.ForEachAsync(async request => 107 { 108 await responseStream.WriteAsync(response); 109 }); 110 } 111 } 112 } 113 114 /// <summary> 115 /// Server runner. 116 /// </summary> 117 public class ServerRunnerImpl : IServerRunner 118 { 119 readonly Server server; 120 readonly TimeStats timeStats = new TimeStats(); 121 ServerRunnerImpl(Server server)122 public ServerRunnerImpl(Server server) 123 { 124 this.server = GrpcPreconditions.CheckNotNull(server); 125 } 126 127 public int BoundPort 128 { 129 get 130 { 131 return server.Ports.Single().BoundPort; 132 } 133 } 134 135 /// <summary> 136 /// Gets server stats. 137 /// </summary> 138 /// <returns>The stats.</returns> GetStats(bool reset)139 public ServerStats GetStats(bool reset) 140 { 141 var timeSnapshot = timeStats.GetSnapshot(reset); 142 143 GrpcEnvironment.Logger.Info("[ServerRunner.GetStats] GC collection counts: gen0 {0}, gen1 {1}, gen2 {2}, (seconds since last reset {3})", 144 GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), timeSnapshot.WallClockTime.TotalSeconds); 145 146 return new ServerStats 147 { 148 TimeElapsed = timeSnapshot.WallClockTime.TotalSeconds, 149 TimeUser = timeSnapshot.UserProcessorTime.TotalSeconds, 150 TimeSystem = timeSnapshot.PrivilegedProcessorTime.TotalSeconds 151 }; 152 } 153 154 /// <summary> 155 /// Asynchronously stops the server. 156 /// </summary> 157 /// <returns>Task that finishes when server has shutdown.</returns> StopAsync()158 public Task StopAsync() 159 { 160 return server.ShutdownAsync(); 161 } 162 } 163 } 164