我一直在尝试对一个后端Kotlin应用程序进行性能评估,它只是拉取一些数据,进行一些数据转换并将其输出,没有什么特别的。其中一个引起我注意的事情是最后一步执行的部分,我们将最终数据倾泻到队列中。起初我注意到当我们启动应用程序时,最后一次网络调用需要很长时间,有时超过一秒钟。通常我们在协程中运行此网络调用,以防止最后一个调用阻塞一切,但我开始尝试单独计时协程和网络调用,并得到了一些奇怪的结果。从我看到的情况来看,与网络调用相比,协程可能需要花费很长时间才能启动/完成。我完全有可能没有正确记录事情,但这是我采用的一般计时方法:
val coroutineTime - Instant.now().toEpochMillis()
GlobalScope.launch {
executionTime = measureTimeMillis { <--DO Message Sending -->}
totalTime = Instant.now().toEpochMillis() - coroutineTime
// Log out execution Time and total time
}
现在我将看到的是类似于
- totalTime = ~800ms
- executionTime = ~150ms
这些并不是一次性的操作,我同时进行了多个这样的进程(我想最多有10个线程),而第一个总时间将始终比实际执行时间/网络调用时间要长得多。最终,在新的几十条消息之后,开销会减少,这些时间将在大约15ms左右变得相同,但是在协程启动时几乎有700ms的开销对我来说似乎是疯狂的。
这是正常/预期的行为吗?我在另一个应用程序中测试过,并看到类似但不那么极端的结果,其中第一个协程需要约70ms才能启动,我很难在使用kotlin的android开发之外找到任何其他此类讨论的例子。
nCores
个协程之后启动的协程,那么这可以解释为什么冷启动会慢。但是,nCores
个协程应该启动得很快,我以为OP是说即使是最开始的那些协程也很慢。 - undefinedDispatchers.IO
来进行双重检查,但结果还是一样,网络调用和协程调用之间存在很大的差异。我唯一能想到的是,在网络调用之前可能有一些相当繁重的处理工作正在进行,而这些工作可能在其他10个线程中进行(它们是由JMSListener管理的线程,所以线程数量根据负载而变化),可能会长时间占用CPU资源。我打算减少线程数量再试一次,因为除此之外,Dispatchers.IO似乎没有产生积极的效果。 - undefined