blob: 5e91d4a96ce91747c6975ffed48d4dd52b231cbf [file] [log] [blame]
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -07001#region Copyright notice and license
2
3// Copyright 2015, Google Inc.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#endregion
33
34using System;
35using System.Collections.Generic;
36using System.Diagnostics;
37using System.IO;
38using System.Linq;
39using System.Text.RegularExpressions;
40using System.Threading;
41using System.Threading.Tasks;
42using Google.Protobuf;
43using Grpc.Core;
44using Grpc.Core.Utils;
45using NUnit.Framework;
46using Grpc.Testing;
47
48namespace Grpc.IntegrationTesting
49{
50 /// <summary>
51 /// Helper methods to start client runners for performance testing.
52 /// </summary>
53 public static class ClientRunners
54 {
55 /// <summary>
56 /// Creates a started client runner.
57 /// </summary>
58 public static IClientRunner CreateStarted(ClientConfig config)
59 {
60 string target = config.ServerTargets.Single();
Jan Tattermusch7a3ee6a2016-02-18 10:36:02 -080061 GrpcPreconditions.CheckArgument(config.LoadParams.LoadCase == LoadParams.LoadOneofCase.ClosedLoop);
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -070062
63 var credentials = config.SecurityParams != null ? TestCredentials.CreateSslCredentials() : ChannelCredentials.Insecure;
64 var channel = new Channel(target, credentials);
65
66 switch (config.RpcType)
67 {
68 case RpcType.UNARY:
Jan Tattermusch18ce9d62015-11-18 15:41:10 -080069 return new SyncUnaryClientRunner(channel,
70 config.PayloadConfig.SimpleParams.ReqSize,
71 config.HistogramParams);
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -070072
73 case RpcType.STREAMING:
74 default:
75 throw new ArgumentException("Unsupported RpcType.");
76 }
77 }
78 }
79
80 /// <summary>
81 /// Client that starts synchronous unary calls in a closed loop.
82 /// </summary>
83 public class SyncUnaryClientRunner : IClientRunner
84 {
Jan Tattermusch18ce9d62015-11-18 15:41:10 -080085 const double SecondsToNanos = 1e9;
86
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -070087 readonly Channel channel;
88 readonly int payloadSize;
89 readonly Histogram histogram;
90
91 readonly BenchmarkService.IBenchmarkServiceClient client;
92 readonly Task runnerTask;
93 readonly CancellationTokenSource stoppedCts;
94 readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
95
Jan Tattermusch18ce9d62015-11-18 15:41:10 -080096 public SyncUnaryClientRunner(Channel channel, int payloadSize, HistogramParams histogramParams)
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -070097 {
Jan Tattermusch7a3ee6a2016-02-18 10:36:02 -080098 this.channel = GrpcPreconditions.CheckNotNull(channel);
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -070099 this.payloadSize = payloadSize;
Jan Tattermusch18ce9d62015-11-18 15:41:10 -0800100 this.histogram = new Histogram(histogramParams.Resolution, histogramParams.MaxPossible);
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -0700101
102 this.stoppedCts = new CancellationTokenSource();
103 this.client = BenchmarkService.NewClient(channel);
104 this.runnerTask = Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning);
105 }
106
107 public ClientStats GetStats(bool reset)
108 {
109 var histogramData = histogram.GetSnapshot(reset);
110 var secondsElapsed = wallClockStopwatch.GetElapsedSnapshot(reset).TotalSeconds;
111
112 // TODO: populate user time and system time
113 return new ClientStats
114 {
115 Latencies = histogramData,
116 TimeElapsed = secondsElapsed,
117 TimeUser = 0,
118 TimeSystem = 0
119 };
120 }
121
122 public async Task StopAsync()
123 {
124 stoppedCts.Cancel();
125 await runnerTask;
126 await channel.ShutdownAsync();
127 }
128
129 private void Run()
130 {
131 var request = new SimpleRequest
132 {
133 Payload = CreateZerosPayload(payloadSize)
134 };
135 var stopwatch = new Stopwatch();
136
137 while (!stoppedCts.Token.IsCancellationRequested)
138 {
139 stopwatch.Restart();
140 client.UnaryCall(request);
141 stopwatch.Stop();
142
Jan Tattermusch18ce9d62015-11-18 15:41:10 -0800143 // spec requires data point in nanoseconds.
144 histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
Jan Tattermuschd0c1bfa2015-10-22 19:14:57 -0700145 }
146 }
147
148 private static Payload CreateZerosPayload(int size)
149 {
150 return new Payload { Body = ByteString.CopyFrom(new byte[size]) };
151 }
152 }
153}