| #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 |
| { |
| /// <summary> |
| /// Helper methods to start server runners for performance testing. |
| /// </summary> |
| public class ServerRunners |
| { |
| static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<ServerRunners>(); |
| |
| /// <summary> |
| /// Creates a started server runner. |
| /// </summary> |
| 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<ChannelOption>(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]; |
| } |
| |
| /// <summary> |
| /// Generic streaming call handler. |
| /// </summary> |
| public async Task StreamingCall(IAsyncStreamReader<byte[]> requestStream, IServerStreamWriter<byte[]> responseStream, ServerCallContext context) |
| { |
| await requestStream.ForEachAsync(async request => |
| { |
| await responseStream.WriteAsync(response); |
| }); |
| } |
| } |
| } |
| |
| /// <summary> |
| /// Server runner. |
| /// </summary> |
| 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; |
| } |
| } |
| |
| /// <summary> |
| /// Gets server stats. |
| /// </summary> |
| /// <returns>The stats.</returns> |
| 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 |
| }; |
| } |
| |
| /// <summary> |
| /// Asynchronously stops the server. |
| /// </summary> |
| /// <returns>Task that finishes when server has shutdown.</returns> |
| public Task StopAsync() |
| { |
| return server.ShutdownAsync(); |
| } |
| } |
| } |