Skip to content

Commit b10480c

Browse files
authored
Client serialization optimizations (#1033)
1 parent fdb9619 commit b10480c

15 files changed

+775
-266
lines changed

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)keys\Grpc.snk</AssemblyOriginatorKeyFile>
1313
<SignAssembly>true</SignAssembly>
1414
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
15+
<CheckEolTargetFramework>false</CheckEolTargetFramework>
1516

1617
<!-- Don't make missing XML docs a fatal build error, but still surface so we have visibility into undocumented APIs. -->
1718
<WarningsNotAsErrors>$(WarningsNotAsErrors);CS1591</WarningsNotAsErrors>

src/Grpc.AspNetCore.Server/Internal/HttpContextSerializationContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public override void Complete()
191191

192192
var data = _bufferWriter.WrittenSpan;
193193

194-
GrpcServerLog.SerializedMessage(_serverCallContext.Logger, typeof(object), data.Length);
194+
GrpcServerLog.SerializedMessage(_serverCallContext.Logger, _serverCallContext.ResponseType, data.Length);
195195
WriteMessage(data);
196196
}
197197
else

src/Grpc.Net.Client/Internal/DefaultSerializationContext.cs

Lines changed: 0 additions & 139 deletions
This file was deleted.
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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;
20+
using Grpc.Core;
21+
using Grpc.Shared;
22+
using Microsoft.Extensions.Logging;
23+
24+
namespace Grpc.Net.Client.Internal
25+
{
26+
internal abstract class GrpcCall
27+
{
28+
// Getting logger name from generic type is slow
29+
private const string LoggerName = "Grpc.Net.Client.Internal.GrpcCall";
30+
31+
private GrpcCallSerializationContext? _serializationContext;
32+
private DefaultDeserializationContext? _deserializationContext;
33+
34+
public GrpcCallSerializationContext SerializationContext
35+
{
36+
get { return _serializationContext ??= new GrpcCallSerializationContext(this); }
37+
}
38+
39+
public DefaultDeserializationContext DeserializationContext
40+
{
41+
get { return _deserializationContext ??= new DefaultDeserializationContext(); }
42+
}
43+
44+
public CallOptions Options { get; }
45+
public ILogger Logger { get; }
46+
public GrpcChannel Channel { get; }
47+
48+
public string? RequestGrpcEncoding { get; internal set; }
49+
50+
public abstract Type RequestType { get; }
51+
public abstract Type ResponseType { get; }
52+
53+
protected GrpcCall(CallOptions options, GrpcChannel channel)
54+
{
55+
Options = options;
56+
Channel = channel;
57+
Logger = channel.LoggerFactory.CreateLogger(LoggerName);
58+
}
59+
}
60+
}

src/Grpc.Net.Client/Internal/GrpcCall.cs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,10 @@
3030

3131
namespace Grpc.Net.Client.Internal
3232
{
33-
internal partial class GrpcCall<TRequest, TResponse> : IDisposable
33+
internal sealed partial class GrpcCall<TRequest, TResponse> : GrpcCall, IDisposable
3434
where TRequest : class
3535
where TResponse : class
3636
{
37-
// Getting logger name from generic type is slow
38-
private const string LoggerName = "Grpc.Net.Client.Internal.GrpcCall";
39-
4037
private readonly CancellationTokenSource _callCts;
4138
private readonly TaskCompletionSource<Status> _callTcs;
4239
private readonly DateTime _deadline;
@@ -51,17 +48,15 @@ internal partial class GrpcCall<TRequest, TResponse> : IDisposable
5148
public bool Disposed { get; private set; }
5249
public bool ResponseFinished { get; private set; }
5350
public HttpResponseMessage? HttpResponse { get; private set; }
54-
public CallOptions Options { get; }
5551
public Method<TRequest, TResponse> Method { get; }
56-
public GrpcChannel Channel { get; }
57-
public ILogger Logger { get; }
5852

5953
// These are set depending on the type of gRPC call
6054
private TaskCompletionSource<TResponse>? _responseTcs;
6155
public HttpContentClientStreamWriter<TRequest, TResponse>? ClientStreamWriter { get; private set; }
6256
public HttpContentClientStreamReader<TRequest, TResponse>? ClientStreamReader { get; private set; }
6357

6458
public GrpcCall(Method<TRequest, TResponse> method, GrpcMethodInfo grpcMethodInfo, CallOptions options, GrpcChannel channel)
59+
: base(options, channel)
6560
{
6661
// Validate deadline before creating any objects that require cleanup
6762
ValidateDeadline(options.Deadline);
@@ -71,9 +66,6 @@ public GrpcCall(Method<TRequest, TResponse> method, GrpcMethodInfo grpcMethodInf
7166
_callTcs = new TaskCompletionSource<Status>();
7267
Method = method;
7368
_grpcMethodInfo = grpcMethodInfo;
74-
Options = options;
75-
Channel = channel;
76-
Logger = channel.LoggerFactory.CreateLogger(LoggerName);
7769
_deadline = options.Deadline ?? DateTime.MaxValue;
7870

7971
Channel.RegisterActiveCall(this);
@@ -94,6 +86,9 @@ public CancellationToken CancellationToken
9486
get { return _callCts.Token; }
9587
}
9688

89+
public override Type RequestType => typeof(TRequest);
90+
public override Type ResponseType => typeof(TResponse);
91+
9792
public void StartUnary(TRequest request)
9893
{
9994
_responseTcs = new TaskCompletionSource<TResponse>(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -386,10 +381,10 @@ private bool TryGetTrailers([NotNullWhen(true)] out Metadata? trailers)
386381

387382
private void SetMessageContent(TRequest request, HttpRequestMessage message)
388383
{
384+
RequestGrpcEncoding = GrpcProtocolHelpers.GetRequestEncoding(message.Headers);
389385
message.Content = new PushUnaryContent<TRequest, TResponse>(
390386
request,
391387
this,
392-
GrpcProtocolHelpers.GetRequestEncoding(message.Headers),
393388
GrpcProtocolConstants.GrpcContentTypeHeaderValue);
394389
}
395390

@@ -519,12 +514,9 @@ private async Task RunCall(HttpRequestMessage request, TimeSpan? timeout)
519514
// Read entire response body immediately and read status from trailers
520515
// Trailers are only available once the response body had been read
521516
var responseStream = await HttpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
522-
var message = await responseStream.ReadMessageAsync(
523-
Logger,
524-
Method.ResponseMarshaller.ContextualDeserializer,
517+
var message = await ReadMessageAsync(
518+
responseStream,
525519
GrpcProtocolHelpers.GetGrpcEncoding(HttpResponse),
526-
Channel.ReceiveMaxMessageSize,
527-
Channel.CompressionProviders,
528520
singleMessage: true,
529521
_callCts.Token).ConfigureAwait(false);
530522
status = GrpcProtocolHelpers.GetResponseStatus(HttpResponse);
@@ -776,7 +768,8 @@ private async Task ReadCredentials(HttpRequestMessage request)
776768

777769
private void CreateWriter(HttpRequestMessage message)
778770
{
779-
ClientStreamWriter = new HttpContentClientStreamWriter<TRequest, TResponse>(this, message);
771+
RequestGrpcEncoding = GrpcProtocolHelpers.GetRequestEncoding(message.Headers);
772+
ClientStreamWriter = new HttpContentClientStreamWriter<TRequest, TResponse>(this);
780773

781774
message.Content = new PushStreamContent<TRequest, TResponse>(ClientStreamWriter, GrpcProtocolConstants.GrpcContentTypeHeaderValue);
782775
}
@@ -898,16 +891,12 @@ private void DeadlineExceeded()
898891
internal ValueTask WriteMessageAsync(
899892
Stream stream,
900893
TRequest message,
901-
string grpcEncoding,
902894
CallOptions callOptions)
903895
{
904896
return stream.WriteMessageAsync(
905-
Logger,
897+
this,
906898
message,
907899
Method.RequestMarshaller.ContextualSerializer,
908-
grpcEncoding,
909-
Channel.SendMaxMessageSize,
910-
Channel.CompressionProviders,
911900
callOptions);
912901
}
913902

@@ -918,6 +907,7 @@ internal ValueTask WriteMessageAsync(
918907
CancellationToken cancellationToken)
919908
{
920909
return responseStream.ReadMessageAsync(
910+
DeserializationContext,
921911
Logger,
922912
Method.ResponseMarshaller.ContextualDeserializer,
923913
grpcEncoding,

0 commit comments

Comments
 (0)