Asynchronous Kotlin:对转换“a”有任何性能影响;“正常”;函数到阻塞挂起函数?
我有一个函数如下所示:Asynchronous Kotlin:对转换“a”有任何性能影响;“正常”;函数到阻塞挂起函数?,asynchronous,kotlin,async-await,coroutine,kotlin-coroutines,Asynchronous,Kotlin,Async Await,Coroutine,Kotlin Coroutines,我有一个函数如下所示: fun <R> map(block: (T) -> R): Result<R> { ... } 所以我有两个问题: 采用“正常”函数,将其作为suspend参数传递,然后阻塞直到结果完成时,是否有任何性能方面的考虑? 根据我所读到的,它听起来像是初始线程在挂起块中继续“工作”,直到它到达第一个挂起点。然后,将延续放入等待队列,初始线程可以自由执行其他工作 然而,在本例中,没有任何“真正的”挂起点,因为实际的函数只是(t)->R,尽管我不知
fun <R> map(block: (T) -> R): Result<R> { ... }
所以我有两个问题:
suspend
参数传递,然后阻塞直到结果完成时,是否有任何性能方面的考虑?
- 根据我所读到的,它听起来像是初始线程在挂起块中继续“工作”,直到它到达第一个挂起点。然后,将延续放入等待队列,初始线程可以自由执行其他工作
- 然而,在本例中,没有任何“真正的”挂起点,因为实际的函数只是
,尽管我不知道编译器是否能够分辨出这一点(t)->R
- 我担心这个设置实际上是在利用池中的另一个线程,它只是通知我的第一个线程要唤醒
您的方法是正确的,
runBlocking
是专门设计用来连接阻塞和非阻塞操作的。从文件中:
运行新的协同程序并中断当前线程,直到其
完成。此函数不应从协同程序中使用<是的
设计用于将常规阻塞代码桥接到编写的库
悬挂式,用于主要功能和测试
还进一步改为:
还有罗曼·艾利扎洛夫的一些有趣的视频:
您的方法是正确的,
runBlocking
是专门设计用来连接阻塞和非阻塞操作的。从文件中:
运行新的协同程序并中断当前线程,直到其
完成。此函数不应从协同程序中使用<是的
设计用于将常规阻塞代码桥接到编写的库
悬挂式,用于主要功能和测试
还进一步改为:
还有罗曼·艾利扎洛夫的一些有趣的视频:
您遇到了臭名昭著的“”问题。这两个世界实际上是分离的,虽然可以添加一个将它们统一起来的表面层,但不能以零性能成本实现。这是非常基本的,即使假设您的
suspend
块从未真正挂起,并且包装层利用了这一假设,甚至没有在其上使用runBlocking
,您仍将付出“准备挂起”的代价。不过,代价并不高:这意味着每次suspend-fun
调用都要创建一个小对象,保存通常驻留在线程本机调用堆栈上的数据。在您的例子中,只有外部块是可挂起的,因此这只是一个这样的对象
runBlocking
在调用它的线程上运行协程,它将在同一线程上同步完成,除非它挂起自己。因此,在suspend
块中有一些同步代码的情况下,线程协调不会对性能造成额外的影响
如果协同程序确实挂起了自身,那么必须有一些外部工作线程对允许协同程序恢复的事件作出反应,并且该线程与原始
runBlocking
线程之间必须有一些协调。这是一个基本的机制,无论是否有协同程序。您遇到了臭名昭著的“”问题。这两个世界实际上是分离的,虽然可以添加一个将它们统一起来的表面层,但不能以零性能成本实现。这是非常基本的,即使假设您的suspend
块从未真正挂起,并且包装层利用了这一假设,甚至没有在其上使用runBlocking
,您仍将付出“准备挂起”的代价。不过,代价并不高:这意味着每次suspend-fun
调用都要创建一个小对象,保存通常驻留在线程本机调用堆栈上的数据。在您的例子中,只有外部块是可挂起的,因此这只是一个这样的对象
runBlocking
在调用它的线程上运行协程,它将在同一线程上同步完成,除非它挂起自己。因此,在suspend
块中有一些同步代码的情况下,线程协调不会对性能造成额外的影响
如果协同程序确实挂起了自身,那么必须有一些外部工作线程对允许协同程序恢复的事件作出反应,并且该线程与原始runBlocking
线程之间必须有一些协调。这是一个基本的机制,无论是否有协同程序
suspend fun <R> mapAsync(block: suspend (T) -> R): Result<R> { ... }
fun <R> map(block: (T) -> R): Result<R> =
runBlocking { mapAsync { block(it) } }