运行 单声道并行似乎并不快

Run mono in parallel doesn't seems faster

所以我尝试并行发出 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())
}

与你的代码无关

你必须明白,任何 i/o-work 大部分时间都是在等待中度过的。等待回复。

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

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

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

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

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

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

上发送回原始线程

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

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

I/O 工作通常更多地是关于编排而不是原始的 cpu 力量。并行计算不会解决慢响应问题,慢响应永远是慢响应。你只会消耗更多的资源而没有好处。

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

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