All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmTest.scheduling.BlockingCoroutineDispatcherMixedStealingStressTest.kt Maven / Gradle / Ivy

There is a newer version: 1.9.0
Show newest version
/*
 * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
 */

package kotlinx.coroutines.scheduling

import kotlinx.coroutines.*
import org.junit.*
import java.util.concurrent.*

/**
 * Specific test that was designed to expose inference between stealing/polling of blocking and non-blocking tasks.RunningThreadStackMergeTest
 */
class BlockingCoroutineDispatcherMixedStealingStressTest : SchedulerTestBase() {

    private val iterations = 10_000

    @Before
    fun setUp() {
        idleWorkerKeepAliveNs = Long.MAX_VALUE
    }

    @Test
    fun testBlockingProgressPreventedInternal()  {
        val blocking = blockingDispatcher(corePoolSize).asExecutor()
        val regular = dispatcher.asExecutor()
        repeat(iterations * stressTestMultiplier) {
            val cpuBlocker = CyclicBarrier(corePoolSize + 1)
            val blockingBlocker = CyclicBarrier(2)
            regular.execute(Runnable {
                // Block all CPU cores except current one
                repeat(corePoolSize - 1) {
                    regular.execute(Runnable {
                        cpuBlocker.await()
                    })
                }

                blocking.execute(Runnable {
                    blockingBlocker.await()
                })

                regular.execute(Runnable {
                    blockingBlocker.await()
                    cpuBlocker.await()
                })
            })
            cpuBlocker.await()
        }
    }

    @Test
    fun testBlockingProgressPreventedExternal()  {
        val blocking = blockingDispatcher(corePoolSize).asExecutor()
        val regular = dispatcher.asExecutor()
        repeat(iterations / 2 * stressTestMultiplier) {
            val cpuBlocker = CyclicBarrier(corePoolSize + 1)
            val blockingBlocker = CyclicBarrier(2)
            repeat(corePoolSize) {
                regular.execute(Runnable {
                    cpuBlocker.await()
                })
            }
            // Wait for all threads to park
            while (true) {
                val waiters = Thread.getAllStackTraces().keys.count { (it.state == Thread.State.TIMED_WAITING || it.state == Thread.State.WAITING)
                        && it is CoroutineScheduler.Worker }
                if (waiters >= corePoolSize) break
                Thread.yield()
            }
            blocking.execute(Runnable {
                blockingBlocker.await()
            })
            regular.execute(Runnable {
            })

            blockingBlocker.await()
            cpuBlocker.await()
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy