运行 单声道并行似乎并不快
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 中如此强大的原因。
它将为您执行所有异步操作,而无需处理线程、锁、同步、连接等。它将使用尽可能少的资源尽快执行所有异步操作。
所以我尝试并行发出 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 中如此强大的原因。
它将为您执行所有异步操作,而无需处理线程、锁、同步、连接等。它将使用尽可能少的资源尽快执行所有异步操作。