问题描述
- 情况1:
bool result = await DoAsync();
- 情况2:
ValueTask<bool> task = DoAsync();
bool result = task.IsCompleted ? task.Result : await task;
通过上面的case 1
和case 2
,
谁能说case 2
的性能(cpu,内存等)更好?
还是task.IsCompleted
只是重复和多余的?
解决方法
要确实知道,您需要使用合适的基准进行测量。但是,我不会期望产生任何重大影响,因为await
已经已经做到了-尽管通过GetAwaiter()
(这不会分配)。实际上,这可能会使真正的异步情况变得更糟。
类似这种优化的 在库代码中很常见,但是当结果可能很同步时,通常用于完全避免使用状态机。时间;例如:
var pending = DoAsync(); // note: not awaited; this is a [Value]Task[<T>]
return pending.IsCompletedSuccessfully
? new ValueTask<Foo>(PostProcess(pending.Result))
: Awaited(pending);
static async ValueTask<Foo> Awaited(ValueTask<Bar> pending)
=> PostProcess(await pending.ConfigureAwait(false));
此处的关键点在于,在这种情况下,原始方法不是 async
,因此我们仅需支付真正异步路径(或故障案例,以使错误堆栈标准化)。
这里有一个Apache phoenix: create phoenix table maps to existing hbase table,显示了此优化的过程;在右侧,您可以看到不使用async
的优化版本,显示为:
async
public ValueTask<Foo> ExampleAsync()
{
ValueTask<Bar> pending = DoAsync();
if (!pending.IsCompletedSuccessfully)
{
return <ExampleAsync>g__Awaited|0_0(pending);
}
return new ValueTask<Foo>(PostProcess(pending.Result));
}
方法是全部:
Awaited
,
情况1很好。如果您根本不使用await
,则可以使用task.IsCompeted。