现在 Kotlin Coroutine 库已经稳定版本,已经出现了很多采用 Coroutine 来重构过去的 RxJava 等异步库的实践,比如 Retrofit 请求使用 Deferred 返回 这些 Coroutine 实践是对异步代码的一个调用模型的改善,callback-> stream -> sequential 的变化。对代码可读性进行了改善。
而 协程 这个概念还有另一个意图,就是减少线程切换开支,在同一个线程里进行 IO 操作,比如 Python Async 用于爬虫的并发 Http 请求方面,在同时发起巨大数量的 Http 请求时,可以创建的协程数量远远高于线程,在同样数量的并发情况下,降低内存的用量和线程的切换开销(实际并没有提高速度,IO 速度才是瓶颈), Python 协程这一特点,得益于“异步 io ”: asyncio,如果使用 requests.get() 这种阻塞请求,是达不到效果的。
回到 Kotlin 的协程,它加入了多线程切换,也就是调度器会把协程分发到不同的线程去跑,这个特性非常好,使用协程也利用了多线程。但问题是,Kotlin 现在没有 “ asyncio ” 这样的机制,也就是说,我没办法在一个线程内发起 n 个协程进行并发 n 个请求,若然,并发其实也是多线程的,也会占很大的线程资源。
所以我的问题是 Kotlin Coroutine 偏向于解决异步编码模型,而不是异步 io 资源的利用效率;而 Python asynio 则偏向于解决异步 io 资源的利用效率( GIL 的存在)?(或许我应该对比 JavaScript? :D)
1
rockyou12 2019-07-25 11:54:30 +08:00
kotlin coroutine 在我的实践中,在计算密集任务中性能起码是略优于 jdk 的 Executor (一点点,可以忽略)。然后异步 io 和现有利用 epoll 的 netty 比好像在性能上并没有优势。
|
2
raiz OP @rockyou12 对的,我表达的意思就是,kotlin coroutine 并没有优化 io 模型,二是优化了代码编写的模型 —— 把回调藏起来。 实际在 io 并发上还是多线程,我记得线程池使用的还是 Executor. 计算密集型,就更不是协程的用途了。btw 你是用 kotlin 做服务端了?
|
3
rockyou12 2019-07-25 12:34:37 +08:00
@raiz 本来就可以写服务端,而且很爽。现在也有直接基于 kotlin coroutine 的 web server。模型应该还是和 Executor 不一样,io 肯定比单纯的 Executor 强得多。
|
4
PDX 2019-07-25 12:38:21 +08:00
我觉得 kotlin coroutine 解决的问题就是让代码可读性更好,写异步更简单。vert.x 里面的回调,rx,到现在的 kotlin coroutine,都是为了解决怎样写异步的代码,而协程才是最吼的!
|
5
rosu 2019-07-25 12:47:41 +08:00 via Android
Python 的协程没有使用过,不评价。kotlin 的协程看起来更像是对线程的再封装。用户自己协商好,最终也要交由分发器处理,后者在根据类型分配到不同线程里去。
回到题目上,在 kotlin 中:其实你把 IO 操作放在 UI 线程的协程里,协程会自行“协商”对应代码的类型。IO 操作不是 CPU 密集,可以只分配一点 CPU 给他跑,而其他任务分配大部分的 CPU。这个也算是“提高异步 IO 资源的利用效率”吧? 个人理解,欢迎讨论 |
6
iPhoneXI 2019-07-25 12:52:22 +08:00 via Android
看来还是 goroutine 最好,M 个协程跑在 N 个线程上
|
7
raiz OP 可以对 Dispatches.IO 线程分配少点 cpu,给 Default 分配多一些的话,是有点意思
|
8
qiyuey 2019-07-25 18:41:20 +08:00 via Android
当只能使用 BIO 的时候需要 Dispatchers.IO ,NIO、AIO 应当使用 Dispatchers.Default。
|