Differentiating between latency-critical operation...
# coroutines
c
Differentiating between latency-critical operations and non-latency-critical operations In large systems, we often have two different categories of operations: • Latency-critical: answering a request from the user… • Non-latency-critical: async events… We have code like:
Copy code
suspend fun doSomething() = coroutineScope {
    val data1 = async { fetchData1() }
    val data2 = async { fetchData2() }
    val data3 = async { fetchData3() }

    doSomething(data1.await(), data2.await(), data3.await())
}
Is there a way to declare that this function should use high parallelism when it's latency-critical, and use parallelism only if the system is idle? We don't want to simply reduce the parallelism of non-critical operations, because if the system is doing few things, having high parallelism for these operations is still beneficial. Maybe some kind of priority? Maybe with another dispatcher?
s
Which resource is under contention? CPU, or network + remote service?
d
If I understood this correctly, I think a dispatcher would solve this issue. Something similar to https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/common/src/internal/LimitedDispatcher.kt, but allocating new workers not just on demand but when some condition is satisfied (for example, either the queue has too many elements or the
coroutineContext
has a special "urgent operation" marker).
c
@Sam CPU.
l
Dispatchers.Default.limitedParallelism
and/or differentiated use of
yield()
in between CPU intensive loops could help you do that
c
@louiscad I don't want to set a limit to parallelism though. I'd like something like
Dispatchers.Default.lowPriority
l
The JVM has a concept of thread priority
I wish Roman Elizarov was still there to provide some guidance on using this right.
c
I'm not sure this use-case warrants creating new threads 🤔
u
Here is a related Github issue from a couple years ago, it has other related issues linked: https://github.com/Kotlin/kotlinx.coroutines/issues/3178
🙏 1
l
Pretty sure you could make a dispatcher wrapper that sets and resets the priority for each dispatch it receives.
try+finally is your friend
c
You mean the OS priority? I think that is quite expensive to set
l
Did you read something about that being expensive? On the JVM, you can do:
Thread.currentThread().priority = something
c
I'm not talking about code size, I'm talking about execution speed. Thread priority is an input into the OS scheduler, and changing its settings on each coroutine dispatch will probably be more expensive than what the coroutines do themselves…
l
I wasn't talking about code size either 🙂 You're saying "probably more expensive", so it's all assumptions… I'd test it. You can change the priority many times, and measure the time it took in nanos