【发布时间】:2022-01-09 00:38:17
【问题描述】:
我正在尝试编写一个并行映射扩展函数来使用协程对列表进行并行映射操作。 但是,我的解决方案有很大的开销,我不知道为什么。
这是我对pmap扩展功能的实现:
fun <T, U> List<T>.pmap(scope: CoroutineScope = GlobalScope,
transform: suspend (T) -> U): List<U> {
return map { i -> scope.async { transform(i) } }.map { runBlocking { it.await() } }
}
但是,当我在普通函数中执行完全相同的操作时,最多需要额外的 100 毫秒(这很多)。 我尝试使用内联,但没有效果。
我将在这里留下我为演示此行为所做的完整测试:
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
fun main() {
test()
}
fun <T, U> List<T>.pmap(scope: CoroutineScope = GlobalScope,
transform: suspend (T) -> U): List<U> {
return this.map { i -> scope.async { transform(i) } }.map { runBlocking { it.await() } }
}
fun test() {
val list = listOf<Long>(100,200,300)
val transform: suspend (Long) -> Long = { long: Long ->
delay(long)
long*2
}
val timeTakenPmap = measureTimeMillis {
list.pmap(GlobalScope) { transform(it) }
}
val manualpmap = measureTimeMillis {
list.map { GlobalScope.async { transform(it) } }
.map { runBlocking { it.await() } }
}
val timeTakenMap = measureTimeMillis {
list.map { runBlocking { transform(it) } }
}
println("pmapTime: $timeTakenPmap - mapTime: $timeTakenMap - manualpmap: $manualpmap")
}
可以在 kotlin 操场上运行:https://pl.kotl.in/CIXVqezg3
在操场上,它会打印以下结果:
pmapTime: 411 - mapTime: 602 - manualpmap: 302
MapTime 和 manualPmap 给出了合理的结果,延迟之外只有 2ms 的时间。但是 pmapTime 很遥远。而且manualpmap和pmap之间的代码在我看来完全一样。
在我自己的机器上它运行得更快一些,pmap 大约需要 350 毫秒。
有人知道为什么会这样吗?
【问题讨论】:
-
这不是对代码进行基准测试的有效方法。一方面,您忽略了预热时间。第一次开始创建协程时,必须创建线程。后续协程可以重用池中的线程实例。你的工作量只有三个项目是微不足道的。查看基准测试库。
-
哦,谢谢。我完全忘记了线程创建时间。我完全确定这就是原因。谢谢。
标签: kotlin kotlin-coroutines kotlin-extension