Skip to content

Commit 6adeb9b

Browse files
authored
Change some internal async Task methods to be async ValueTask (dotnet/corefx#40527)
We have some internal and private `async Task` methods that are only ever `await`ed. Today there's no benefit to making them `async ValueTask` methods, so we've kept them as `async Task`. However, if we end up changing the implementation of `async ValueTask` to pool underlying objects, there becomes a potential benefit to using `async ValueTask` for these instead of `async Task`. This PR changes those in a variety of libraries where we care more about performance and allocations. There are likely a few more methods we'd want to convert based on profiling, but I believe this represents the bulk of them. Commit migrated from dotnet/corefx@97d9fb9
1 parent 08b76ee commit 6adeb9b

File tree

23 files changed

+78
-79
lines changed

23 files changed

+78
-79
lines changed

src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ private ValueTask SendFrameAsync(MessageOpcode opcode, bool endOfMessage, ReadOn
370370
// Similarly, it should be rare that there are multiple outstanding calls to SendFrameAsync, but if there are, again
371371
// fall back to the fallback path.
372372
return cancellationToken.CanBeCanceled || !_sendFrameAsyncLock.Wait(0) ?
373-
new ValueTask(SendFrameFallbackAsync(opcode, endOfMessage, payloadBuffer, cancellationToken)) :
373+
SendFrameFallbackAsync(opcode, endOfMessage, payloadBuffer, cancellationToken) :
374374
SendFrameLockAcquiredNonCancelableAsync(opcode, endOfMessage, payloadBuffer);
375375
}
376376

@@ -421,10 +421,10 @@ private ValueTask SendFrameLockAcquiredNonCancelableAsync(MessageOpcode opcode,
421421
}
422422
}
423423

424-
return new ValueTask(WaitForWriteTaskAsync(writeTask));
424+
return WaitForWriteTaskAsync(writeTask);
425425
}
426426

427-
private async Task WaitForWriteTaskAsync(ValueTask writeTask)
427+
private async ValueTask WaitForWriteTaskAsync(ValueTask writeTask)
428428
{
429429
try
430430
{
@@ -443,7 +443,7 @@ private async Task WaitForWriteTaskAsync(ValueTask writeTask)
443443
}
444444
}
445445

446-
private async Task SendFrameFallbackAsync(MessageOpcode opcode, bool endOfMessage, ReadOnlyMemory<byte> payloadBuffer, CancellationToken cancellationToken)
446+
private async ValueTask SendFrameFallbackAsync(MessageOpcode opcode, bool endOfMessage, ReadOnlyMemory<byte> payloadBuffer, CancellationToken cancellationToken)
447447
{
448448
await _sendFrameAsyncLock.WaitAsync(cancellationToken).ConfigureAwait(false);
449449
try
@@ -781,7 +781,7 @@ private async ValueTask<TWebSocketReceiveResult> ReceiveAsyncPrivate<TWebSocketR
781781
/// <summary>Processes a received close message.</summary>
782782
/// <param name="header">The message header.</param>
783783
/// <returns>The received result message.</returns>
784-
private async Task HandleReceivedCloseAsync(MessageHeader header, CancellationToken cancellationToken)
784+
private async ValueTask HandleReceivedCloseAsync(MessageHeader header, CancellationToken cancellationToken)
785785
{
786786
lock (StateUpdateLock)
787787
{
@@ -848,7 +848,7 @@ private async Task HandleReceivedCloseAsync(MessageHeader header, CancellationTo
848848
}
849849

850850
/// <summary>Issues a read on the stream to wait for EOF.</summary>
851-
private async Task WaitForServerToCloseConnectionAsync(CancellationToken cancellationToken)
851+
private async ValueTask WaitForServerToCloseConnectionAsync(CancellationToken cancellationToken)
852852
{
853853
// Per RFC 6455 7.1.1, try to let the server close the connection. We give it up to a second.
854854
// We simply issue a read and don't care what we get back; we could validate that we don't get
@@ -876,7 +876,7 @@ private async Task WaitForServerToCloseConnectionAsync(CancellationToken cancell
876876

877877
/// <summary>Processes a received ping or pong message.</summary>
878878
/// <param name="header">The message header.</param>
879-
private async Task HandleReceivedPingPongAsync(MessageHeader header, CancellationToken cancellationToken)
879+
private async ValueTask HandleReceivedPingPongAsync(MessageHeader header, CancellationToken cancellationToken)
880880
{
881881
// Consume any (optional) payload associated with the ping/pong.
882882
if (header.PayloadLength > 0 && _receiveBufferCount < header.PayloadLength)
@@ -949,7 +949,7 @@ private static bool IsValidCloseStatus(WebSocketCloseStatus closeStatus)
949949
/// <param name="closeStatus">The close status code to use.</param>
950950
/// <param name="error">The error reason.</param>
951951
/// <param name="innerException">An optional inner exception to include in the thrown exception.</param>
952-
private async Task CloseWithReceiveErrorAndThrowAsync(
952+
private async ValueTask CloseWithReceiveErrorAndThrowAsync(
953953
WebSocketCloseStatus closeStatus, WebSocketError error, Exception innerException = null)
954954
{
955955
// Close the connection if it hasn't already been closed
@@ -1132,7 +1132,7 @@ private async Task CloseAsyncPrivate(WebSocketCloseStatus closeStatus, string st
11321132
/// <param name="closeStatus">The close status to send.</param>
11331133
/// <param name="closeStatusDescription">The close status description to send.</param>
11341134
/// <param name="cancellationToken">The CancellationToken to use to cancel the websocket.</param>
1135-
private async Task SendCloseFrameAsync(WebSocketCloseStatus closeStatus, string closeStatusDescription, CancellationToken cancellationToken)
1135+
private async ValueTask SendCloseFrameAsync(WebSocketCloseStatus closeStatus, string closeStatusDescription, CancellationToken cancellationToken)
11361136
{
11371137
// Close payload is two bytes containing the close status followed by a UTF8-encoding of the status description, if it exists.
11381138

@@ -1193,7 +1193,7 @@ private void ConsumeFromBuffer(int count)
11931193
_receiveBufferOffset += count;
11941194
}
11951195

1196-
private async Task EnsureBufferContainsAsync(int minimumRequiredBytes, CancellationToken cancellationToken, bool throwOnPrematureClosure = true)
1196+
private async ValueTask EnsureBufferContainsAsync(int minimumRequiredBytes, CancellationToken cancellationToken, bool throwOnPrematureClosure = true)
11971197
{
11981198
Debug.Assert(minimumRequiredBytes <= _receiveBuffer.Length, $"Requested number of bytes {minimumRequiredBytes} must not exceed {_receiveBuffer.Length}");
11991199

src/libraries/System.IO.Compression.Brotli/src/System/IO/Compression/enc/BrotliStream.Compress.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati
7676
EnsureNoActiveAsyncOperation();
7777
EnsureNotDisposed();
7878

79-
return new ValueTask(cancellationToken.IsCancellationRequested ?
80-
Task.FromCanceled<int>(cancellationToken) :
81-
WriteAsyncMemoryCore(buffer, cancellationToken));
79+
return cancellationToken.IsCancellationRequested ?
80+
new ValueTask(Task.FromCanceled<int>(cancellationToken)) :
81+
WriteAsyncMemoryCore(buffer, cancellationToken);
8282
}
8383

84-
private async Task WriteAsyncMemoryCore(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken, bool isFinalBlock = false)
84+
private async ValueTask WriteAsyncMemoryCore(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken, bool isFinalBlock = false)
8585
{
8686
AsyncOperationStarting();
8787
try

src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateZLib/DeflateStream.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ private void PurgeBuffers(bool disposing)
631631
}
632632
}
633633

634-
private async Task PurgeBuffersAsync()
634+
private async ValueTask PurgeBuffersAsync()
635635
{
636636
// Same logic as PurgeBuffers, except with async counterparts.
637637

@@ -809,12 +809,12 @@ internal ValueTask WriteAsyncMemory(ReadOnlyMemory<byte> buffer, CancellationTok
809809
EnsureNoActiveAsyncOperation();
810810
EnsureNotDisposed();
811811

812-
return new ValueTask(cancellationToken.IsCancellationRequested ?
813-
Task.FromCanceled<int>(cancellationToken) :
814-
WriteAsyncMemoryCore(buffer, cancellationToken));
812+
return cancellationToken.IsCancellationRequested ?
813+
new ValueTask(Task.FromCanceled<int>(cancellationToken)) :
814+
WriteAsyncMemoryCore(buffer, cancellationToken);
815815
}
816816

817-
private async Task WriteAsyncMemoryCore(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
817+
private async ValueTask WriteAsyncMemoryCore(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
818818
{
819819
AsyncOperationStarting();
820820
try
@@ -838,7 +838,7 @@ private async Task WriteAsyncMemoryCore(ReadOnlyMemory<byte> buffer, Cancellatio
838838
/// <summary>
839839
/// Writes the bytes that have already been deflated
840840
/// </summary>
841-
private async Task WriteDeflaterOutputAsync(CancellationToken cancellationToken)
841+
private async ValueTask WriteDeflaterOutputAsync(CancellationToken cancellationToken)
842842
{
843843
Debug.Assert(_deflater != null && _buffer != null);
844844
while (!_deflater.NeedsInput())

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ private static void SetBasicAuthToken(HttpRequestMessage request, NetworkCredent
184184
SetRequestAuthenticationHeaderValue(request, new AuthenticationHeaderValue(BasicScheme, base64AuthString), isProxyAuth);
185185
}
186186

187-
private static async Task<bool> TrySetDigestAuthToken(HttpRequestMessage request, NetworkCredential credential, DigestResponse digestResponse, bool isProxyAuth)
187+
private static async ValueTask<bool> TrySetDigestAuthToken(HttpRequestMessage request, NetworkCredential credential, DigestResponse digestResponse, bool isProxyAuth)
188188
{
189189
string parameter = await GetDigestTokenForCredential(credential, request, digestResponse).ConfigureAwait(false);
190190

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingReadStream.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ private enum ParsingState : byte
429429

430430
public override bool NeedsDrain => (_connection != null);
431431

432-
public override async Task<bool> DrainAsync(int maxDrainBytes)
432+
public override async ValueTask<bool> DrainAsync(int maxDrainBytes)
433433
{
434434
Debug.Assert(_connection != null);
435435

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ChunkedEncodingWriteStream.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationTo
3131
// Don't write if nothing was given, especially since we don't want to accidentally send a 0 chunk,
3232
// which would indicate end of body. Instead, just ensure no content is stuck in the buffer.
3333
connection.FlushAsync() :
34-
new ValueTask(WriteChunkAsync(connection, buffer));
34+
WriteChunkAsync(connection, buffer);
3535

3636
return task;
3737

38-
static async Task WriteChunkAsync(HttpConnection connection, ReadOnlyMemory<byte> buffer)
38+
static async ValueTask WriteChunkAsync(HttpConnection connection, ReadOnlyMemory<byte> buffer)
3939
{
4040
// Write chunk length in hex followed by \r\n
4141
await connection.WriteHexInt32Async(buffer.Length).ConfigureAwait(false);
@@ -47,7 +47,7 @@ static async Task WriteChunkAsync(HttpConnection connection, ReadOnlyMemory<byte
4747
}
4848
}
4949

50-
public override async Task FinishAsync()
50+
public override async ValueTask FinishAsync()
5151
{
5252
// Send 0 byte chunk to indicate end, then final CrLf
5353
HttpConnection connection = GetConnectionOrThrow();

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthReadStream.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ private ReadOnlyMemory<byte> ReadFromConnectionBuffer(int maxBytesToRead)
191191

192192
public override bool NeedsDrain => (_connection != null);
193193

194-
public override async Task<bool> DrainAsync(int maxDrainBytes)
194+
public override async ValueTask<bool> DrainAsync(int maxDrainBytes)
195195
{
196196
Debug.Assert(_connection != null);
197197
Debug.Assert(_contentBytesRemaining > 0);

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ContentLengthWriteStream.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationTo
2323
// that are still buffered.
2424
HttpConnection connection = GetConnectionOrThrow();
2525
Debug.Assert(connection._currentRequest != null);
26-
return new ValueTask(connection.WriteAsync(buffer));
26+
return connection.WriteAsync(buffer);
2727
}
2828

29-
public override Task FinishAsync()
29+
public override ValueTask FinishAsync()
3030
{
3131
_connection = null;
32-
return Task.CompletedTask;
32+
return default;
3333
}
3434
}
3535
}

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/CreditManager.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ public ValueTask<int> RequestCreditAsync(int amount, CancellationToken cancellat
6464
var waiter = new Waiter { Amount = amount };
6565
(_waiters ??= new Queue<Waiter>()).Enqueue(waiter);
6666

67-
return new ValueTask<int>(cancellationToken.CanBeCanceled ?
68-
waiter.WaitWithCancellationAsync(cancellationToken) :
69-
waiter.Task);
67+
return cancellationToken.CanBeCanceled ?
68+
waiter.WaitWithCancellationAsync(cancellationToken) :
69+
new ValueTask<int>(waiter.Task);
7070
}
7171
}
7272

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public Http2Connection(HttpConnectionPool pool, Stream stream)
127127

128128
private object SyncObject => _httpStreams;
129129

130-
public async Task SetupAsync()
130+
public async ValueTask SetupAsync()
131131
{
132132
_outgoingBuffer.EnsureAvailableSpace(s_http2ConnectionPreface.Length +
133133
FrameHeader.Size + (FrameHeader.SettingLength * 2) +
@@ -165,7 +165,7 @@ public async Task SetupAsync()
165165
_ = ProcessIncomingFramesAsync();
166166
}
167167

168-
private async Task EnsureIncomingBytesAsync(int minReadBytes)
168+
private async ValueTask EnsureIncomingBytesAsync(int minReadBytes)
169169
{
170170
if (NetEventSource.IsEnabled) Trace($"{nameof(minReadBytes)}={minReadBytes}");
171171
if (_incomingBuffer.ActiveLength >= minReadBytes)
@@ -321,7 +321,7 @@ private Http2Stream GetStream(int streamId)
321321
}
322322
}
323323

324-
private async Task ProcessHeadersFrame(FrameHeader frameHeader)
324+
private async ValueTask ProcessHeadersFrame(FrameHeader frameHeader)
325325
{
326326
if (NetEventSource.IsEnabled) Trace($"{frameHeader}");
327327
Debug.Assert(frameHeader.Type == FrameType.Headers);
@@ -783,7 +783,7 @@ private void EndWrite(bool forceFlush)
783783
}
784784
}
785785

786-
private async Task AcquireWriteLockAsync(CancellationToken cancellationToken)
786+
private async ValueTask AcquireWriteLockAsync(CancellationToken cancellationToken)
787787
{
788788
Task acquireLockTask = _writerLock.WaitAsync(cancellationToken);
789789
if (!acquireLockTask.IsCompletedSuccessfully)

0 commit comments

Comments
 (0)