kotlin delay()有效持续时间来自非父作用域的干扰(不可预测的行为?)

ccrfmcuu  于 2023-02-09  发布在  Kotlin
关注(0)|答案(1)|浏览(127)

早上好,我发现使用协程的库内部的延迟要比传递的值多得多(这是5000毫秒,但往往需要长达20秒)我最初假设一些库内部问题,这是导致继续不能按时调用..但我无法找到这个“问题”,改变了范围调度程序,以unconfined在库中没有改变什么,而且所有内核的CPU使用率都很低(5%),因此我使用该库的coroutineContext进行了一些测试。
存储库上下文为:BLACKBOX_ACTOR.coroutineContext

val threadPool = Executors.newFixedThreadPool(10)
        fun busyCoreDelay(ms:Int){ // CONF WORKS ALWAYS 
            val tstart=System.currentTimeMillis()
            while(System.currentTimeMillis()-tstart<ms){
                //noop
            }
        }
        withContext( CoroutineName("Test") + Job() +Dispatchers.Unconfined){
            GlobalScope.launch(BLACKBOX_ACTOR.coroutineContext+ Job() + Dispatchers.IO+CoroutineName("Test2") ){ // AA with this DOESNTWORKS
                //GlobalScope.launch(CoroutineName("Test3") + Job() +Dispatchers.Unconfined){ // AB with this WORKS (only if AA is not present!)
                GlobalScope.launch(CoroutineName("Test3") + Job() +threadPool.asCoroutineDispatcher()){ // AC (works with AB , doesn't with AA )
                while(isActive){

                    val tstart=System.currentTimeMillis()
                    //delay(5000) // PROBLEM1
                    busyCoreDelay(5000)
                    val tend=System.currentTimeMillis()
                    val delaydelta=tend-tstart
                    log.warn { "inner delaydelta = ${delaydelta}" }
                }
                }
            }
//
        }

主要问题是为什么即使父进程在非受限Dispatchers中,delay也会超过标称值(这是在库内部,代码在此处发布很复杂,但非受限Dispatchers不应避免delay()调用占用太多时间(给定cpu几乎为0?)
而且......为什么我调用“delay(5000)//PROBLEM 1”时AA + AB or AA+AC不起作用,而用// AB or AB+AC起作用?
据我所知,内部作业应该从BLACKBOX_ACTOR中转义任何父协程上下文和调度程序(busyCoreDelay始终适用于所有配置)
非常感谢

iqjalb3h

iqjalb3h1#

找到了!问题是从一个(我的)内部库中使用Dispatchers.Unconfined,这导致代码在kotlinx.coroutines.DefaultExecutor上执行,一旦任何代码在kotlinx.coroutines.DefaultExecutor上运行,延迟就会变得“不稳定”(考虑到在其他代码正在执行时没有到达延续点,它显然无法按时调度)
这触发了其它库中的错误行为,使上游调用超时等等。
现在,我将把答案标记为已完成,因为问题实际上是我的错误,没有注意到Dispatchers.Unconfined的使用
(启用最大日志级别,并在程序日志中查找在kotlinx.coroutines.DefaultExecutor上执行的代码)
我希望它对其他遇到同类问题的人也会有用,
我还要感谢所有对原问题提出评论的人。

相关问题