【问题标题】:Run mono in parallel doesn't seems faster并行运行单声道似乎并不快
【发布时间】:2021-10-28 11:49:46
【问题描述】:

所以我正在尝试并行发出 API 请求,但它似乎并没有更快。我做错了吗?这是我的代码。

 fun getUserInfo(username: String): Mono<String> {
        return webclient
            // some config and params
            .post()
            .bodyToMono(String::class)
            .subscribeOn(Schedulers.parallel())
}

fun main(){
    val time = measureTimeMillis {
        Mono.zip(getUserInfo("doge"), getUserInfo("cheems"), etc...)
            .map { user ->listOf(it.t1, it.t2, etc...) }
            .block()
    }
   // give the same amount of time doesn't seems faster 
   // with and without subscribeOn(Schedulers.parallel())
}

【问题讨论】:

  • 您的代码看起来不错。它应该花费与这些请求中最慢的一样多的时间。您的测量结果究竟显示了什么?另外,请注意,当您启动应用程序并发送第一个请求时,WebClient 有一些恒定的初始化时间。

标签: kotlin reactive-programming spring-webflux


【解决方案1】:

与你的代码无关。

您必须了解,任何 i/o 工作大部分都花在等待上。就像在等待响应一样。

如果我们查看线程的生命周期,它会做一些预处理然后发送请求。发送请求后,它必须等待响应。这是花费大部分时间的地方,然后您会收到响应并处理响应。事情是这样的,多达 90% 的请求时间可以花在等待上。让线程等待会浪费很多资源。

这就是 webflux/reactor 的优点。发送请求时,线程不会等待,它将继续处理其他请求/响应,当第一个请求响应返回时,任何空闲线程都可以接收该响应,它不必是线程它首先发送了请求。

我刚才描述的通常是所谓的异步或异步工作。

让我们看看你在做什么。您希望并行运行您的请求,这意味着同时在多个内核上使用多个线程。

为此,您需要联系其他 cpu 并告诉他们为即将到来的工作做好准备。然后 cpu 需要在每个 cpu 上初始化多个线程,然后必须将数据发送到所有 cpu。如您所见,此处涉及设置时间。

那么所有的请求都是同时从多个cpu发出的,但是等待响应的时间是不变的!它的等待时间与以前完全相同(高达总请求时间的 90%)。然后当所有响应都返回时,它们会在多个 cpu 上收集和处理,然后在原始 cpu 上发送回原始线程。

你得到了什么?很可能几乎没有,但您也很可能为了这个非常非常小的收益而使用了更多的资源。

如果您需要原始 cpu 计算能力,例如某种计算,例如 3D 渲染器,或者我不知道,破解哈希等不是 i/o 工作,并行通常很好。

I/O 工作通常更多是关于编排而不是原始 CPU 功率。慢响应不会通过并行计算来解决 慢响应总是慢响应。你只会消耗更多的资源而没有好处。

这就是为什么只有普通的flatMap 在 reactor 中如此强大的原因。

它将为您执行所有异步操作,而无需处理线程、锁、同步、连接等。它将使用尽可能少的资源尽可能快地异步执行所有工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-31
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    相关资源
    最近更新 更多