Skip to content

Commit 91e749c

Browse files
committed
Remove async state machine from MySqlCommand methods.
This reduces allocations in the "ExecuteScalarNewAsync" scenario by 3%.
1 parent 1f76567 commit 91e749c

File tree

3 files changed

+41
-31
lines changed

3 files changed

+41
-31
lines changed

src/MySqlConnector/MySqlClient/MySqlCommand.cs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -114,30 +114,23 @@ protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) =>
114114
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken) =>
115115
ExecuteNonQueryAsync(Connection.AsyncIOBehavior, cancellationToken);
116116

117-
internal async Task<int> ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
118-
{
119-
VerifyValid();
120-
return await m_commandExecutor.ExecuteNonQueryAsync(CommandText, m_parameterCollection, ioBehavior, cancellationToken).ConfigureAwait(false);
121-
}
117+
internal Task<int> ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) =>
118+
!IsValid(out var exception) ? Utility.TaskFromException<int>(exception) :
119+
m_commandExecutor.ExecuteNonQueryAsync(CommandText, m_parameterCollection, ioBehavior, cancellationToken);
122120

123121
public override Task<object> ExecuteScalarAsync(CancellationToken cancellationToken) =>
124122
ExecuteScalarAsync(Connection.AsyncIOBehavior, cancellationToken);
125123

126-
internal async Task<object> ExecuteScalarAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
127-
{
128-
VerifyValid();
129-
return await m_commandExecutor.ExecuteScalarAsync(CommandText, m_parameterCollection, ioBehavior, cancellationToken).ConfigureAwait(false);
130-
}
124+
internal Task<object> ExecuteScalarAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) =>
125+
!IsValid(out var exception) ? Utility.TaskFromException<object>(exception) :
126+
m_commandExecutor.ExecuteScalarAsync(CommandText, m_parameterCollection, ioBehavior, cancellationToken);
131127

132128
protected override Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) =>
133129
ExecuteReaderAsync(behavior, Connection.AsyncIOBehavior, cancellationToken);
134130

135-
internal async Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior,
136-
CancellationToken cancellationToken)
137-
{
138-
VerifyValid();
139-
return await m_commandExecutor.ExecuteReaderAsync(CommandText, m_parameterCollection, behavior, ioBehavior, cancellationToken).ConfigureAwait(false);
140-
}
131+
internal Task<DbDataReader> ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) =>
132+
!IsValid(out var exception) ? Utility.TaskFromException<DbDataReader>(exception) :
133+
m_commandExecutor.ExecuteReaderAsync(CommandText, m_parameterCollection, behavior, ioBehavior, cancellationToken);
141134

142135
protected override void Dispose(bool disposing)
143136
{
@@ -181,15 +174,25 @@ private void VerifyNotDisposed()
181174

182175
private void VerifyValid()
183176
{
184-
VerifyNotDisposed();
185-
if (DbConnection == null)
186-
throw new InvalidOperationException("Connection property must be non-null.");
187-
if (DbConnection.State != ConnectionState.Open && DbConnection.State != ConnectionState.Connecting)
188-
throw new InvalidOperationException("Connection must be Open; current state is {0}".FormatInvariant(DbConnection.State));
189-
if (DbTransaction != Connection.CurrentTransaction)
190-
throw new InvalidOperationException("The transaction associated with this command is not the connection's active transaction.");
191-
if (string.IsNullOrWhiteSpace(CommandText))
192-
throw new InvalidOperationException("CommandText must be specified");
177+
Exception exception;
178+
if (!IsValid(out exception))
179+
throw exception;
180+
}
181+
182+
private bool IsValid(out Exception exception)
183+
{
184+
exception = null;
185+
if (m_parameterCollection == null)
186+
exception = new ObjectDisposedException(GetType().Name);
187+
else if (DbConnection == null)
188+
exception = new InvalidOperationException("Connection property must be non-null.");
189+
else if (DbConnection.State != ConnectionState.Open && DbConnection.State != ConnectionState.Connecting)
190+
exception = new InvalidOperationException("Connection must be Open; current state is {0}".FormatInvariant(DbConnection.State));
191+
else if (DbTransaction != Connection.CurrentTransaction)
192+
exception = new InvalidOperationException("The transaction associated with this command is not the connection's active transaction.");
193+
else if (string.IsNullOrWhiteSpace(CommandText))
194+
exception = new InvalidOperationException("CommandText must be specified");
195+
return exception == null;
193196
}
194197

195198
internal void ReaderClosed() => (m_commandExecutor as StoredProcedureCommandExecutor)?.SetParams();

src/MySqlConnector/Utility.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Runtime.InteropServices;
55
using System.Text;
6+
using System.Threading.Tasks;
67

78
namespace MySql.Data
89
{
@@ -43,6 +44,17 @@ public static ArraySegment<T> Slice<T>(this ArraySegment<T> arraySegment, int in
4344
public static ArraySegment<T> Slice<T>(this ArraySegment<T> arraySegment, int index, int length) =>
4445
new ArraySegment<T>(arraySegment.Array, arraySegment.Offset + index, length);
4546

47+
#if !NETSTANDARD1_3
48+
public static Task<T> TaskFromException<T>(Exception exception)
49+
{
50+
var tcs = new TaskCompletionSource<T>();
51+
tcs.SetException(exception);
52+
return tcs.Task;
53+
}
54+
#else
55+
public static Task<T> TaskFromException<T>(Exception exception) => Task.FromException<T>(exception);
56+
#endif
57+
4658
#if !NETSTANDARD1_3
4759
public static bool TryGetBuffer(this MemoryStream memoryStream, out ArraySegment<byte> buffer)
4860
{

src/MySqlConnector/ValueTaskExtensions.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ public static ValueTask<TResult> ContinueWith<T, TResult>(this ValueTask<T> valu
1111
new ValueTask<TResult>(valueTask.AsTask().ContinueWith(task => continuation(task.GetAwaiter().GetResult()).AsTask()).Unwrap());
1212
}
1313

14-
public static ValueTask<T> FromException<T>(Exception exception)
15-
{
16-
var tcs = new TaskCompletionSource<T>();
17-
tcs.SetException(exception);
18-
return new ValueTask<T>(tcs.Task);
19-
}
14+
public static ValueTask<T> FromException<T>(Exception exception) => new ValueTask<T>(Utility.TaskFromException<T>(exception));
2015
}
2116
}

0 commit comments

Comments
 (0)