From 016657a13a7d5859ab3c9d60d1fc3b7d204af1d7 Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Sat, 12 Aug 2023 20:41:21 -0700 Subject: [PATCH] Avoid Task allocation on sync path. --- src/MySqlConnector/Core/CommandExecutor.cs | 2 +- src/MySqlConnector/MySqlBatch.cs | 8 +++++--- src/MySqlConnector/MySqlCommand.cs | 22 +++++++++++++++------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/MySqlConnector/Core/CommandExecutor.cs b/src/MySqlConnector/Core/CommandExecutor.cs index 752329a4b..0434a8314 100644 --- a/src/MySqlConnector/Core/CommandExecutor.cs +++ b/src/MySqlConnector/Core/CommandExecutor.cs @@ -8,7 +8,7 @@ namespace MySqlConnector.Core; internal static class CommandExecutor { - public static async Task ExecuteReaderAsync(IReadOnlyList commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken) + public static async ValueTask ExecuteReaderAsync(IReadOnlyList commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken) { try { diff --git a/src/MySqlConnector/MySqlBatch.cs b/src/MySqlConnector/MySqlBatch.cs index f7a0257bc..1f1ab42f6 100644 --- a/src/MySqlConnector/MySqlBatch.cs +++ b/src/MySqlConnector/MySqlBatch.cs @@ -134,7 +134,9 @@ private DbDataReader ExecuteDbDataReader(CommandBehavior behavior) #endif { this.ResetCommandTimeout(); - return ExecuteReaderAsync(behavior, IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult(); +#pragma warning disable CA2012 // OK to read .Result because the ValueTask is completed + return ExecuteReaderAsync(behavior, IOBehavior.Synchronous, CancellationToken.None).Result; +#pragma warning restore CA2012 } #if NET6_0_OR_GREATER @@ -148,10 +150,10 @@ private async Task ExecuteDbDataReaderAsync(CommandBehavior behavi return await ExecuteReaderAsync(behavior, AsyncIOBehavior, cancellationToken).ConfigureAwait(false); } - private Task ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) + private ValueTask ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) { if (!IsValid(out var exception)) - return Task.FromException(exception); + return new ValueTask(Task.FromException(exception)); CurrentCommandBehavior = behavior; foreach (MySqlBatchCommand batchCommand in BatchCommands) diff --git a/src/MySqlConnector/MySqlCommand.cs b/src/MySqlConnector/MySqlCommand.cs index a933a8935..aa3b7db88 100644 --- a/src/MySqlConnector/MySqlCommand.cs +++ b/src/MySqlConnector/MySqlCommand.cs @@ -109,9 +109,11 @@ private MySqlCommand(MySqlCommand other) /// public override object? ExecuteScalar() => ExecuteScalarAsync(IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult(); - public new MySqlDataReader ExecuteReader() => ExecuteReaderAsync(default, IOBehavior.Synchronous, default).GetAwaiter().GetResult(); +#pragma warning disable CA2012 // OK to read .Result because the ValueTask is completed + public new MySqlDataReader ExecuteReader() => ExecuteReaderAsync(default, IOBehavior.Synchronous, default).Result; public new MySqlDataReader ExecuteReader(CommandBehavior commandBehavior) => ExecuteReaderAsync(commandBehavior, IOBehavior.Synchronous, default).GetAwaiter().GetResult(); +#pragma warning restore CA2012 /// public override void Prepare() @@ -278,8 +280,10 @@ protected override DbTransaction? DbTransaction protected override DbParameter CreateDbParameter() => new MySqlParameter(); +#pragma warning disable CA2012 // OK to read .Result because the ValueTask is completed protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) => - ExecuteReaderAsync(behavior, IOBehavior.Synchronous, CancellationToken.None).GetAwaiter().GetResult(); + ExecuteReaderAsync(behavior, IOBehavior.Synchronous, CancellationToken.None).Result; +#pragma warning restore CA2012 /// /// Executes this command asynchronously on the associated . @@ -332,15 +336,15 @@ internal async Task ExecuteNonQueryAsync(IOBehavior ioBehavior, Cancellatio } public new Task ExecuteReaderAsync(CancellationToken cancellationToken = default) => - ExecuteReaderAsync(default, AsyncIOBehavior, cancellationToken); + ExecuteReaderAsync(default, AsyncIOBehavior, cancellationToken).AsTask(); public new Task ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken = default) => - ExecuteReaderAsync(behavior, AsyncIOBehavior, cancellationToken); + ExecuteReaderAsync(behavior, AsyncIOBehavior, cancellationToken).AsTask(); protected override async Task ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) => await ExecuteReaderAsync(behavior, AsyncIOBehavior, cancellationToken).ConfigureAwait(false); - internal async Task ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) + internal async ValueTask ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) { Volatile.Write(ref m_commandTimedOut, false); this.ResetCommandTimeout(); @@ -348,10 +352,14 @@ internal async Task ExecuteReaderAsync(CommandBehavior behavior return await ExecuteReaderNoResetTimeoutAsync(behavior, ioBehavior, cancellationToken).ConfigureAwait(false); } - internal Task ExecuteReaderNoResetTimeoutAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) + internal ValueTask ExecuteReaderNoResetTimeoutAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) { if (!IsValid(out var exception)) - return Task.FromException(exception); +#if NET5_0_OR_GREATER + return ValueTask.FromException(exception); +#else + return new ValueTask(Task.FromException(exception)); +#endif var activity = NoActivity ? null : Connection!.Session.StartActivity(ActivitySourceHelper.ExecuteActivityName, ActivitySourceHelper.DatabaseStatementTagName, CommandText);