[尝试一个简单的应用程序,其中一个使用协程添加variable i
,另一个使用Completable
中的RxJava
。
公司代码:
val timeCoroutineStart = System.currentTimeMillis()
CoroutineScope(Dispatchers.IO).launch {
var i = 0
repeat(1000000000) {
i++
}
Log.d(
"TASK_TIME",
"COROUTINE: ${System.currentTimeMillis() - timeCoroutineStart}"
)
}.start()
Rx代码:
val timeRxStart = System.currentTimeMillis()
Completable.create{
var i = 0
repeat(1000000000) {
i++
}
it.onComplete()
}.subscribeOn(Schedulers.io()).subscribe {
Log.d(
"TASK_TIME",
"RX: ${System.currentTimeMillis() - timeRxStart}"
)
}
结果:
D/TASK_TIME: RX: 1720
D/TASK_TIME: COROUTINE: 20873
我使用协程还很陌生,想尝试一些非常简单的方法。值得注意的是,较小的for循环协程为MUCH faster
。我使用错了吗?还是协程比RX更长的计算时间有缺点?
编辑
在JVM(不是Android)上运行Coroutine代码与Rx非常相似,因此,在Android上运行的完全相同的代码具有与在JVM上运行不同的性能
var i = 0
repeat(1000000000) {
i++
}
这是一种非常幼稚的微标记方法。 JIT编译器将整个循环变为无操作,而只是将最终结果直接分配给i。基本上,您还没有建立任何相关且稳定的结果。
此外,由于您并不是真正测试框架的功能,而是以琐碎的方式使用它们,而整个逻辑都在一个代码块中,所以即使更改循环也无济于事。
您应该对基准进行更接近于预期用例的基准测试,并且应该将测量本身放在外部循环中,重复相同的测量几秒钟并取平均值。最好还应该从统计信息中减去大约第一秒,以避免预热效应。
这不是你的方式launch a coroutine
,
根据您的情况,上述方法的主体在main thread
中执行。这就是为什么it's slow
!您需要launch a suspend method
包含heavy work
!尝试:-
val timeCoroutineStart = System.currentTimeMillis()
CoroutineScope(Dispatchers.IO).launch {
comparison()
}
suspend fun comparison() {
withContext(Dispatchers.DEFAULT) {
var i = 0
repeat(1000000000) {
i++
}
Log.d(
"TASK_TIME",
"COROUTINE: ${System.currentTimeMillis() - timeCoroutineStart}"
)
}
}
您可以从Comparision获得有关RXJava和协程的性能的更多详细信息:>
在RXJava和协程的比较中,最重要的因素是内存和CPU消耗。