Skip to content

Commit 9c8a3dc

Browse files
committed
Inline TryAsync to reduce Func<> allocations.
This reduces allocations in the "ManyRowsNewSync" scenario by 24%.
1 parent 908b5a2 commit 9c8a3dc

File tree

1 file changed

+45
-53
lines changed

1 file changed

+45
-53
lines changed

src/MySqlConnector/Serialization/MySqlSession.cs

Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -287,23 +287,62 @@ public async Task<bool> TryPingAsync(IOBehavior ioBehavior, CancellationToken ca
287287
public ValueTask<int> SendAsync(PayloadData payload, IOBehavior ioBehavior, CancellationToken cancellationToken)
288288
{
289289
m_payloadHandler.StartNewConversation();
290-
return TryAsync(m_payloadHandler.WritePayloadAsync, payload.ArraySegment, ioBehavior, cancellationToken);
290+
return SendReplyAsync(payload, ioBehavior, cancellationToken);
291291
}
292292

293293
// Starts a new conversation with the server by receiving the first packet.
294294
public ValueTask<PayloadData> ReceiveAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
295295
{
296296
m_payloadHandler.StartNewConversation();
297-
return TryAsync(m_payloadHandler.ReadPayloadAsync, ioBehavior, cancellationToken);
297+
return ReceiveReplyAsync(ioBehavior, cancellationToken);
298298
}
299299

300300
// Continues a conversation with the server by receiving a response to a packet sent with 'Send' or 'SendReply'.
301-
public ValueTask<PayloadData> ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) =>
302-
TryAsync(m_payloadHandler.ReadPayloadAsync, ioBehavior, cancellationToken);
301+
public ValueTask<PayloadData> ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
302+
{
303+
ValueTask<ArraySegment<byte>> task;
304+
try
305+
{
306+
VerifyConnected();
307+
task = m_payloadHandler.ReadPayloadAsync(ProtocolErrorBehavior.Throw, ioBehavior);
308+
}
309+
catch (Exception ex)
310+
{
311+
task = ValueTaskExtensions.FromException<ArraySegment<byte>>(ex);
312+
}
313+
314+
if (task.IsCompletedSuccessfully)
315+
{
316+
var payload = new PayloadData(task.Result);
317+
if (payload.HeaderByte != ErrorPayload.Signature)
318+
return new ValueTask<PayloadData>(payload);
319+
320+
var exception = ErrorPayload.Create(payload).ToException();
321+
return ValueTaskExtensions.FromException<PayloadData>(exception);
322+
}
323+
324+
return new ValueTask<PayloadData>(task.AsTask().ContinueWith(TryAsyncContinuation, cancellationToken, TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default));
325+
}
303326

304327
// Continues a conversation with the server by sending a reply to a packet received with 'Receive' or 'ReceiveReply'.
305-
public ValueTask<int> SendReplyAsync(PayloadData payload, IOBehavior ioBehavior, CancellationToken cancellationToken) =>
306-
TryAsync(m_payloadHandler.WritePayloadAsync, payload.ArraySegment, ioBehavior, cancellationToken);
328+
public ValueTask<int> SendReplyAsync(PayloadData payload, IOBehavior ioBehavior, CancellationToken cancellationToken)
329+
{
330+
ValueTask<int> task;
331+
try
332+
{
333+
VerifyConnected();
334+
task = m_payloadHandler.WritePayloadAsync(payload.ArraySegment, ioBehavior);
335+
}
336+
catch (Exception ex)
337+
{
338+
task = ValueTaskExtensions.FromException<int>(ex);
339+
}
340+
341+
if (task.IsCompletedSuccessfully)
342+
return task;
343+
344+
return new ValueTask<int>(task.AsTask().ContinueWith(TryAsyncContinuation, cancellationToken, TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default));
345+
}
307346

308347
private void VerifyConnected()
309348
{
@@ -565,26 +604,6 @@ private void ShutdownSocket()
565604
}
566605
}
567606

568-
private ValueTask<int> TryAsync<TArg>(Func<TArg, IOBehavior, ValueTask<int>> func, TArg arg, IOBehavior ioBehavior, CancellationToken cancellationToken)
569-
{
570-
ValueTask<int> task;
571-
try
572-
{
573-
VerifyConnected();
574-
task = func(arg, ioBehavior);
575-
}
576-
catch (Exception ex)
577-
{
578-
task = ValueTaskExtensions.FromException<int>(ex);
579-
}
580-
581-
if (task.IsCompletedSuccessfully)
582-
return task;
583-
584-
return new ValueTask<int>(task.AsTask()
585-
.ContinueWith(TryAsyncContinuation, cancellationToken, TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default));
586-
}
587-
588607
private int TryAsyncContinuation(Task<int> task)
589608
{
590609
if (task.IsFaulted)
@@ -595,33 +614,6 @@ private int TryAsyncContinuation(Task<int> task)
595614
return 0;
596615
}
597616

598-
private ValueTask<PayloadData> TryAsync(Func<ProtocolErrorBehavior, IOBehavior, ValueTask<ArraySegment<byte>>> func, IOBehavior ioBehavior, CancellationToken cancellationToken)
599-
{
600-
ValueTask<ArraySegment<byte>> task;
601-
try
602-
{
603-
VerifyConnected();
604-
task = func(ProtocolErrorBehavior.Throw, ioBehavior);
605-
}
606-
catch (Exception ex)
607-
{
608-
task = ValueTaskExtensions.FromException<ArraySegment<byte>>(ex);
609-
}
610-
611-
if (task.IsCompletedSuccessfully)
612-
{
613-
var payload = new PayloadData(task.Result);
614-
if (payload.HeaderByte != ErrorPayload.Signature)
615-
return new ValueTask<PayloadData>(payload);
616-
617-
var exception = ErrorPayload.Create(payload).ToException();
618-
return ValueTaskExtensions.FromException<PayloadData>(exception);
619-
}
620-
621-
return new ValueTask<PayloadData>(task.AsTask()
622-
.ContinueWith(TryAsyncContinuation, cancellationToken, TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default));
623-
}
624-
625617
private PayloadData TryAsyncContinuation(Task<ArraySegment<byte>> task)
626618
{
627619
if (task.IsFaulted)

0 commit comments

Comments
 (0)