Skip to content

Commit 1275462

Browse files
authored
Add client microbenchmark (#484)
1 parent e1488b7 commit 1275462

File tree

9 files changed

+128
-14
lines changed

9 files changed

+128
-14
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#region Copyright notice and license
2+
3+
// Copyright 2019 The 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.IO;
20+
using System.Net;
21+
using System.Net.Http;
22+
using System.Net.Http.Headers;
23+
using System.Threading.Tasks;
24+
using BenchmarkDotNet.Attributes;
25+
using Greet;
26+
using Grpc.AspNetCore.Microbenchmarks.Internal;
27+
using Grpc.Net.Client;
28+
using Grpc.Tests.Shared;
29+
30+
namespace Grpc.AspNetCore.Microbenchmarks.Client
31+
{
32+
public class UnaryClientBenchmark
33+
{
34+
private Greeter.GreeterClient? _client;
35+
36+
[GlobalSetup]
37+
public void GlobalSetup()
38+
{
39+
var ms = new MemoryStream();
40+
MessageHelpers.WriteMessage(ms, new HelloReply());
41+
var requestMessage = ms.ToArray();
42+
43+
var handler = TestHttpMessageHandler.Create(r =>
44+
{
45+
var content = new ByteArrayContent(requestMessage);
46+
content.Headers.ContentType = new MediaTypeHeaderValue("application/grpc");
47+
48+
return Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.OK, content));
49+
});
50+
51+
var httpClient = new HttpClient(handler);
52+
53+
var channel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
54+
{
55+
HttpClient = httpClient
56+
});
57+
58+
_client = new Greeter.GreeterClient(channel);
59+
}
60+
61+
[Benchmark]
62+
public Task HandleCallAsync()
63+
{
64+
return _client!.SayHelloAsync(new HelloRequest()).ResponseAsync;
65+
}
66+
}
67+
}

perf/Grpc.AspNetCore.Microbenchmarks/Grpc.AspNetCore.Microbenchmarks.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111

1212
<ItemGroup>
1313
<Protobuf Include=".\Proto\chat.proto" GrpcServices="Server" />
14+
<Protobuf Include=".\Proto\greet.proto" GrpcServices="Client" />
1415

16+
<Compile Include="..\..\test\Shared\ClientTestHelpers.cs" Link="Internal\ClientTestHelpers.cs" />
17+
<Compile Include="..\..\test\Shared\ResponseUtils.cs" Link="Internal\ResponseUtils.cs" />
18+
<Compile Include="..\..\test\Shared\TaskExtensions.cs" Link="Internal\TaskExtensions.cs" />
19+
<Compile Include="..\..\test\Shared\TestHttpMessageHandler.cs" Link="Internal\TestHttpMessageHandler.cs" />
1520
<Compile Include="..\..\test\Shared\TestRequestBodyPipeFeature.cs" Link="Internal\TestRequestBodyPipeFeature.cs" />
1621
<Compile Include="..\..\test\Shared\TestResponseBodyFeature.cs" Link="Internal\TestResponseBodyFeature.cs" />
1722

perf/Grpc.AspNetCore.Microbenchmarks/Program.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,24 @@ static void Main(string[] args)
2929
}
3030
#else
3131
// Profiling option. This will call methods explicitly, in-process
32-
static async Task Main(string[] args)
32+
static async System.Threading.Tasks.Task Main(string[] args)
3333
{
34-
UnaryServerCallHandlerBenchmark benchmark = new UnaryServerCallHandlerBenchmark();
34+
var benchmark = new Client.UnaryClientBenchmark();
3535
benchmark.GlobalSetup();
3636
for (var i = 0; i < 100; i++)
3737
{
3838
await benchmark.HandleCallAsync();
3939
}
4040

41-
Console.WriteLine("Press any key to start.");
42-
Console.ReadKey();
41+
System.Console.WriteLine("Press any key to start.");
42+
System.Console.ReadKey();
4343
for (var i = 0; i < 1; i++)
4444
{
4545
await benchmark.HandleCallAsync();
4646
}
4747

48-
Console.WriteLine("Done. Press any key to exit.");
49-
Console.ReadKey();
48+
System.Console.WriteLine("Done. Press any key to exit.");
49+
System.Console.ReadKey();
5050
}
5151
#endif
5252
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2019 The gRPC Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
syntax = "proto3";
16+
17+
package Greet;
18+
19+
import "google/protobuf/timestamp.proto";
20+
21+
// The greeting service definition.
22+
service Greeter {
23+
// Sends a greeting
24+
rpc SayHello (HelloRequest) returns (HelloReply);
25+
rpc SayHellos (HelloRequest) returns (stream HelloReply);
26+
}
27+
28+
// The request message containing the user's name.
29+
message HelloRequest {
30+
string name = 1;
31+
}
32+
33+
// The response message containing the greetings
34+
message HelloReply {
35+
string message = 1;
36+
google.protobuf.Timestamp timestamp = 2;
37+
}

perf/Grpc.AspNetCore.Microbenchmarks/DeadlineUnaryServerCallHandlerBenchmark.cs renamed to perf/Grpc.AspNetCore.Microbenchmarks/Server/DeadlineUnaryServerCallHandlerBenchmark.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
using Grpc.AspNetCore.Server.Internal;
2222
using Microsoft.AspNetCore.Http;
2323

24-
namespace Grpc.AspNetCore.Microbenchmarks
24+
namespace Grpc.AspNetCore.Microbenchmarks.Server
2525
{
2626
public class DeadlineUnaryServerCallHandlerBenchmark : UnaryServerCallHandlerBenchmarkBase
2727
{

perf/Grpc.AspNetCore.Microbenchmarks/InterceptedUnaryServerCallHandlerBenchmark.cs renamed to perf/Grpc.AspNetCore.Microbenchmarks/Server/InterceptedUnaryServerCallHandlerBenchmark.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
using BenchmarkDotNet.Attributes;
2121
using Grpc.AspNetCore.Microbenchmarks.Internal;
2222

23-
namespace Grpc.AspNetCore.Microbenchmarks
23+
namespace Grpc.AspNetCore.Microbenchmarks.Server
2424
{
2525
public class InterceptedUnaryServerCallHandlerBenchmark : UnaryServerCallHandlerBenchmarkBase
2626
{

perf/Grpc.AspNetCore.Microbenchmarks/UnaryServerCallHandlerBenchmark.cs renamed to perf/Grpc.AspNetCore.Microbenchmarks/Server/UnaryServerCallHandlerBenchmark.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
using System.Threading.Tasks;
2020
using BenchmarkDotNet.Attributes;
2121

22-
namespace Grpc.AspNetCore.Microbenchmarks
22+
namespace Grpc.AspNetCore.Microbenchmarks.Server
2323
{
2424
public class UnaryServerCallHandlerBenchmark : UnaryServerCallHandlerBenchmarkBase
2525
{

perf/Grpc.AspNetCore.Microbenchmarks/UnaryServerCallHandlerBenchmarkBase.cs renamed to perf/Grpc.AspNetCore.Microbenchmarks/Server/UnaryServerCallHandlerBenchmarkBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
using Microsoft.Extensions.DependencyInjection.Extensions;
3636
using Microsoft.Extensions.Logging.Abstractions;
3737

38-
namespace Grpc.AspNetCore.Microbenchmarks
38+
namespace Grpc.AspNetCore.Microbenchmarks.Server
3939
{
4040
public class UnaryServerCallHandlerBenchmarkBase
4141
{

test/Shared/ResponseUtils.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,20 @@
2222
using System.IO;
2323
using System.Net;
2424
using System.Net.Http;
25+
using System.Net.Http.Headers;
2526
using System.Threading;
2627
using System.Threading.Tasks;
2728
using Grpc.Core;
28-
using Grpc.Net.Client.Internal;
2929

3030
namespace Grpc.Tests.Shared
3131
{
3232
internal static class ResponseUtils
3333
{
34+
internal static readonly MediaTypeHeaderValue GrpcContentTypeHeaderValue = new MediaTypeHeaderValue("application/grpc");
35+
internal const string MessageEncodingHeader = "grpc-encoding";
36+
internal const string IdentityGrpcEncoding = "identity";
37+
internal const string StatusTrailer = "grpc-status";
38+
3439
public static HttpResponseMessage CreateResponse(HttpStatusCode statusCode) =>
3540
CreateResponse(statusCode, string.Empty);
3641

@@ -39,18 +44,18 @@ public static HttpResponseMessage CreateResponse(HttpStatusCode statusCode, stri
3944

4045
public static HttpResponseMessage CreateResponse(HttpStatusCode statusCode, HttpContent payload, StatusCode? grpcStatusCode = StatusCode.OK, string? grpcEncoding = null)
4146
{
42-
payload.Headers.ContentType = GrpcProtocolConstants.GrpcContentTypeHeaderValue;
47+
payload.Headers.ContentType = GrpcContentTypeHeaderValue;
4348

4449
var message = new HttpResponseMessage(statusCode)
4550
{
4651
Content = payload
4752
};
4853

49-
message.Headers.Add(GrpcProtocolConstants.MessageEncodingHeader, grpcEncoding ?? GrpcProtocolConstants.IdentityGrpcEncoding);
54+
message.Headers.Add(MessageEncodingHeader, grpcEncoding ?? IdentityGrpcEncoding);
5055

5156
if (grpcStatusCode != null)
5257
{
53-
message.TrailingHeaders.Add(GrpcProtocolConstants.StatusTrailer, grpcStatusCode.Value.ToString("D"));
58+
message.TrailingHeaders.Add(StatusTrailer, grpcStatusCode.Value.ToString("D"));
5459
}
5560

5661
return message;

0 commit comments

Comments
 (0)