#region Copyright notice and license // Copyright 2015 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using Google.Protobuf; using Grpc.Core; using Grpc.Core.Logging; using Grpc.Core.Utils; using NUnit.Framework; using Grpc.Testing; namespace Grpc.IntegrationTesting { /// /// Helper methods to start server runners for performance testing. /// public class ServerRunners { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType(); /// /// Creates a started server runner. /// public static IServerRunner CreateStarted(ServerConfig config) { Logger.Debug("ServerConfig: {0}", config); var credentials = config.SecurityParams != null ? TestCredentials.CreateSslServerCredentials() : ServerCredentials.Insecure; if (config.AsyncServerThreads != 0) { Logger.Warning("ServerConfig.AsyncServerThreads is not supported for C#. Ignoring the value"); } if (config.CoreLimit != 0) { Logger.Warning("ServerConfig.CoreLimit is not supported for C#. Ignoring the value"); } if (config.CoreList.Count > 0) { Logger.Warning("ServerConfig.CoreList is not supported for C#. Ignoring the value"); } ServerServiceDefinition service = null; if (config.ServerType == ServerType.AsyncServer) { GrpcPreconditions.CheckArgument(config.PayloadConfig == null, "ServerConfig.PayloadConfig shouldn't be set for BenchmarkService based server."); service = BenchmarkService.BindService(new BenchmarkServiceImpl()); } else if (config.ServerType == ServerType.AsyncGenericServer) { var genericService = new GenericServiceImpl(config.PayloadConfig.BytebufParams.RespSize); service = GenericService.BindHandler(genericService.StreamingCall); } else { throw new ArgumentException("Unsupported ServerType"); } var channelOptions = new List(config.ChannelArgs.Select((arg) => arg.ToChannelOption())); var server = new Server(channelOptions) { Services = { service }, Ports = { new ServerPort("[::]", config.Port, credentials) } }; server.Start(); return new ServerRunnerImpl(server); } private class GenericServiceImpl { readonly byte[] response; public GenericServiceImpl(int responseSize) { this.response = new byte[responseSize]; } /// /// Generic streaming call handler. /// public async Task StreamingCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async request => { await responseStream.WriteAsync(response); }); } } } /// /// Server runner. /// public class ServerRunnerImpl : IServerRunner { readonly Server server; readonly TimeStats timeStats = new TimeStats(); public ServerRunnerImpl(Server server) { this.server = GrpcPreconditions.CheckNotNull(server); } public int BoundPort { get { return server.Ports.Single().BoundPort; } } /// /// Gets server stats. /// /// The stats. public ServerStats GetStats(bool reset) { var timeSnapshot = timeStats.GetSnapshot(reset); GrpcEnvironment.Logger.Info("[ServerRunner.GetStats] GC collection counts: gen0 {0}, gen1 {1}, gen2 {2}, (seconds since last reset {3})", GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), timeSnapshot.WallClockTime.TotalSeconds); return new ServerStats { TimeElapsed = timeSnapshot.WallClockTime.TotalSeconds, TimeUser = timeSnapshot.UserProcessorTime.TotalSeconds, TimeSystem = timeSnapshot.PrivilegedProcessorTime.TotalSeconds }; } /// /// Asynchronously stops the server. /// /// Task that finishes when server has shutdown. public Task StopAsync() { return server.ShutdownAsync(); } } }