1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-09 17:44:48 +09:00

Reduce allocations in Quic/HTTP3 (#104394)

* Reduce allocations in Quic/HTTP3

* Also wait for WritesClosed when there's no content
This commit is contained in:
Miha Zupan 2024-07-08 14:03:36 +02:00 committed by GitHub
parent 26b6161c6b
commit 2d9203420a
Signed by: github
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 24 deletions

View file

@ -172,15 +172,9 @@ namespace System.Net.Http
await FlushSendBufferAsync(endStream: _request.Content == null, _requestBodyCancellationSource.Token).ConfigureAwait(false);
}
Task sendRequestTask;
if (_request.Content != null)
{
sendRequestTask = SendContentAsync(_request.Content!, _requestBodyCancellationSource.Token);
}
else
{
sendRequestTask = Task.CompletedTask;
}
Task sendRequestTask = _request.Content != null
? SendContentAsync(_request.Content, _requestBodyCancellationSource.Token)
: Task.CompletedTask;
// In parallel, send content and read response.
// Depending on Expect 100 Continue usage, one will depend on the other making progress.
@ -219,6 +213,23 @@ namespace System.Net.Http
// Wait for the response headers to be read.
await readResponseTask.ConfigureAwait(false);
// If we've sent a body, wait for the writes to be closed (most likely already done).
// If sendRequestTask hasn't completed yet, we're doing duplex content transfers and can't wait for writes to be closed yet.
if (sendRequestTask.IsCompletedSuccessfully &&
_stream.WritesClosed is { IsCompletedSuccessfully: false } writesClosed)
{
try
{
await writesClosed.WaitAsync(_requestBodyCancellationSource.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// If the request got cancelled before WritesClosed completed, avoid leaking an unobserved task exception.
_connection.LogExceptions(writesClosed);
throw;
}
}
Debug.Assert(_response != null && _response.Content != null);
// Set our content stream.
var responseContent = (HttpConnectionResponseContent)_response.Content;
@ -460,7 +471,6 @@ namespace System.Net.Http
else
{
_stream.CompleteWrites();
await _stream.WritesClosed.ConfigureAwait(false);
}
if (HttpTelemetry.Log.IsEnabled()) HttpTelemetry.Log.RequestContentStop(bytesWritten);
@ -523,17 +533,11 @@ namespace System.Net.Http
}
}
private async ValueTask FlushSendBufferAsync(bool endStream, CancellationToken cancellationToken)
private ValueTask FlushSendBufferAsync(bool endStream, CancellationToken cancellationToken)
{
await _stream.WriteAsync(_sendBuffer.ActiveMemory, endStream, cancellationToken).ConfigureAwait(false);
_sendBuffer.Discard(_sendBuffer.ActiveLength);
await _stream.FlushAsync(cancellationToken).ConfigureAwait(false);
if (endStream)
{
await _stream.WritesClosed.ConfigureAwait(false);
}
ReadOnlyMemory<byte> toSend = _sendBuffer.ActiveMemory;
_sendBuffer.Discard(toSend.Length);
return _stream.WriteAsync(toSend, endStream, cancellationToken);
}
private async ValueTask DrainContentLength0Frames(CancellationToken cancellationToken)

View file

@ -310,6 +310,13 @@ internal sealed class ResettableValueTaskSource : IValueTaskSource
{
if (_finalTaskSource is null)
{
if (_isSignaled)
{
return _exception is null
? Task.CompletedTask
: Task.FromException(_exception);
}
_finalTaskSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
if (!_isCompleted)
{
@ -319,10 +326,6 @@ internal sealed class ResettableValueTaskSource : IValueTaskSource
((GCHandle)state!).Free();
}, handle, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
if (_isSignaled)
{
TrySignal(out _);
}
}
return _finalTaskSource.Task;
}