首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有必要检查`ValueTask.IsCompleted`的性能?

是否有必要检查`ValueTask.IsCompleted`的性能?
EN

Stack Overflow用户
提问于 2020-09-09 12:49:30
回答 2查看 659关注 0票数 1
  • 案例1:

代码语言:javascript
复制
bool result = await DoAsync();

  • case 2:

代码语言:javascript
复制
ValueTask<bool> task = DoAsync();
bool result = task.IsCompleted ? task.Result : await task;

上面的case 1case 2

有人能说case 2对性能(cpu、内存等)更好吗?

或者,task.IsCompleted只是重复和多余的吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-09 12:55:02

要确切地知道,您需要使用合适的基准进行度量。不过,我不认为这会产生任何重大影响,因为await已经做到了这一点--尽管是通过GetAwaiter() (不分配)。它实际上可能会使真正的异步场景变得更糟。

类似于此优化的内容在库代码中很常见,但通常用于避免状态机在很多时候结果可能是同步的情况下完全避免状态机;例如:

代码语言:javascript
复制
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开销(或者在失败的情况下,用于标准化错误堆栈)。

下面是一个sharplab.io link,它显示了优化的过程;在右边,您可以看到不使用async的优化版本,其结果如下:

代码语言:javascript
复制
    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方法是

代码语言:javascript
复制
    [AsyncStateMachine(typeof(<<ExampleAsync>g__Awaited|0_0>d))]
    [CompilerGenerated]
    internal static ValueTask<Foo> <ExampleAsync>g__Awaited|0_0(ValueTask<Bar> pending)
    {
        <<ExampleAsync>g__Awaited|0_0>d stateMachine = default(<<ExampleAsync>g__Awaited|0_0>d);
        stateMachine.pending = pending;
        stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<Foo>.Create();
        stateMachine.<>1__state = -1;
        stateMachine.<>t__builder.Start(ref stateMachine);
        return stateMachine.<>t__builder.Task;
    }
    [StructLayout(LayoutKind.Auto)]
    [CompilerGenerated]
    private struct <<ExampleAsync>g__Awaited|0_0>d : IAsyncStateMachine
    {
        public int <>1__state;

        public AsyncValueTaskMethodBuilder<Foo> <>t__builder;

        public ValueTask<Bar> pending;

        private ConfiguredValueTaskAwaitable<Bar>.ConfiguredValueTaskAwaiter <>u__1;

        private void MoveNext()
        {
            int num = <>1__state;
            Foo result;
            try
            {
                ConfiguredValueTaskAwaitable<Bar>.ConfiguredValueTaskAwaiter awaiter;
                if (num != 0)
                {
                    awaiter = pending.ConfigureAwait(false).GetAwaiter();
                    if (!awaiter.IsCompleted)
                    {
                        num = (<>1__state = 0);
                        <>u__1 = awaiter;
                        <>t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this);
                        return;
                    }
                }
                else
                {
                    awaiter = <>u__1;
                    <>u__1 = default(ConfiguredValueTaskAwaitable<Bar>.ConfiguredValueTaskAwaiter);
                    num = (<>1__state = -1);
                }
                result = PostProcess(awaiter.GetResult());
            }
            catch (Exception exception)
            {
                <>1__state = -2;
                <>t__builder.SetException(exception);
                return;
            }
            <>1__state = -2;
            <>t__builder.SetResult(result);
        }

        void IAsyncStateMachine.MoveNext()
        {
            //ILSpy generated this explicit interface implementation from .override directive in MoveNext
            this.MoveNext();
        }

        [DebuggerHidden]
        private void SetStateMachine(IAsyncStateMachine stateMachine)
        {
            <>t__builder.SetStateMachine(stateMachine);
        }

        void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
        {
            //ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
            this.SetStateMachine(stateMachine);
        }
    }
票数 3
EN

Stack Overflow用户

发布于 2020-09-09 12:53:29

案子1没问题。如果根本不使用task.IsCompeted,就会使用await

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63812073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档