Fast-path async in PagedBufferedTextWriter

This commit is contained in:
Ben Adams 2018-09-01 00:53:24 +01:00 committed by Ryan Nowak
parent fabe189470
commit 337bc462de
1 changed files with 55 additions and 8 deletions

View File

@ -28,14 +28,28 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
// Don't do anything. We'll call FlushAsync.
}
public override async Task FlushAsync()
public override Task FlushAsync() => FlushAsyncCore();
// private non-virtual for internal calling
private Task FlushAsyncCore()
{
var length = _charBuffer.Length;
if (length == 0)
{
return;
// If nothing sync buffered return CompletedTask,
// so we can fast-path skip async state-machine creation
return Task.CompletedTask;
}
return FlushAsyncAwaited();
}
private async Task FlushAsyncAwaited()
{
var length = _charBuffer.Length;
Debug.Assert(length > 0);
var pages = _charBuffer.Pages;
var count = pages.Count;
for (var i = 0; i < count; i++)
@ -89,21 +103,54 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal
_charBuffer.Append(value);
}
public override async Task WriteAsync(char value)
public override Task WriteAsync(char value)
{
await FlushAsync();
var flushTask = FlushAsyncCore();
// FlushAsyncCore will return CompletedTask if nothing sync buffered
// Fast-path and skip async state-machine if only a single async operation
return ReferenceEquals(flushTask, Task.CompletedTask) ?
_inner.WriteAsync(value) :
WriteAsyncAwaited(flushTask, value);
}
private async Task WriteAsyncAwaited(Task flushTask, char value)
{
await flushTask;
await _inner.WriteAsync(value);
}
public override async Task WriteAsync(char[] buffer, int index, int count)
public override Task WriteAsync(char[] buffer, int index, int count)
{
await FlushAsync();
var flushTask = FlushAsyncCore();
// FlushAsyncCore will return CompletedTask if nothing sync buffered
// Fast-path and skip async state-machine if only a single async operation
return ReferenceEquals(flushTask, Task.CompletedTask) ?
_inner.WriteAsync(buffer, index, count) :
WriteAsyncAwaited(flushTask, buffer, index, count);
}
private async Task WriteAsyncAwaited(Task flushTask, char[] buffer, int index, int count)
{
await flushTask;
await _inner.WriteAsync(buffer, index, count);
}
public override async Task WriteAsync(string value)
public override Task WriteAsync(string value)
{
await FlushAsync();
var flushTask = FlushAsyncCore();
// FlushAsyncCore will return CompletedTask if nothing sync buffered
// Fast-path and skip async state-machine if only a single async operation
return ReferenceEquals(flushTask, Task.CompletedTask) ?
_inner.WriteAsync(value) :
WriteAsyncAwaited(flushTask, value);
}
private async Task WriteAsyncAwaited(Task flushTask, string value)
{
await flushTask;
await _inner.WriteAsync(value);
}