You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编写异步例程:选用start还是Promise.then?

Raku异步例程:start块 vs 链式Promise的性能分析

问题背景

你提供了JavaScript的async/await异步函数示例,随后在Raku中实现了两种等价异步逻辑:

  • 使用start { }包装协程,配合await编写异步代码
  • 使用Promise链式调用(.then)实现逻辑

通过基准测试发现链式Promise速度更快,但代码复杂度更高,因此提出两个问题:


问题1:当前链式Promise确实更快,还是基准测试存在误导?

你的基准测试存在明显误导,原因在于test-then的写法不符合真正的异步Promise链式调用规范:

sub test-then {
    Promise.kept(42).then({
        my $data := $_.result;
        my $second-data := $data.is-prime;
        # 这里调用了.result,会同步阻塞当前线程等待内层Promise完成
        Promise.kept.then({
            my $result := $second-data == False ?? 'ok' !! 'err';
            $result;
        }).result; # 关键问题:同步阻塞
    })
}

在then回调中调用.result会强制同步等待内层Promise完成,这相当于把异步逻辑变成了同步执行,完全跳过了Raku异步调度器的协程挂起/恢复流程。而test-start中的await会正常触发协程挂起,让调度器处理其他任务,这部分调度开销是test-then没有的,因此测试结果中链式Promise更快,但这是测试代码人为制造的差异,而非两种异步写法的真实性能差距。

如果修正test-then为标准的链式异步写法(去掉.result,让Promise链自然异步流转):

sub test-then {
    Promise.kept(42).then({
        my $data := $_.result;
        my $second-data := $data.is-prime;
        Promise.kept.then({
            $second-data == False ?? 'ok' !! 'err';
        })
    })
}

此时两种写法的性能差距会大幅缩小,因为都要经过异步调度器的处理。


问题2:未来Rakudo优化后,start方式能否追上链式Promise的速度?

完全有可能,甚至在优化后start+await的写法性能会更优,原因如下:

  1. 底层实现逻辑趋同:start { }配合await本质是Raku编译器将协程代码转换成状态机,和链式Promise的底层调度逻辑是同源的,两者的核心开销都是异步调度器的协程管理。
  2. 当前差距的来源:当前start+await的性能劣势主要来自协程挂起/恢复的额外开销,这部分是Rakudo实现层面的优化空间,而非语言设计的固有缺陷。
  3. 写法的可读性优势:start+await更接近JavaScriptasync/await的直观写法,编译器可以针对这种结构化的异步代码做更多优化(比如减少不必要的协程切换),而链式Promise的嵌套写法优化空间相对有限。

从长远来看,Rakudo对协程调度的持续优化(比如减少上下文切换开销、优化await的状态机生成)会让start+await的性能逐步追上甚至超过链式Promise。


内容的提问来源于stack exchange,提问作者fingolfin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:25:08