Hey guys, I have a piece of code which was making ...
# coroutines
a
Hey guys, I have a piece of code which was making a single request to get something and then producing a calculation with the result. The first get (getPotatos) was taking around X milliseconds. But now I have to get two things and I’ve came up with the following solution. Although my problem is that now the first get is taking twice the time it was taking in first place. Is it possible that the way I’m doing the requests concurrently can affect each other?
Copy code
suspend fun getApples(): List<Apple> = ...

suspend fun getPotatos(): List<Potato> = ...

fun work(): ReceiveChannel<SomeResult> = GlobalScope.produce {

    try {
        val (apples, potatos) = coroutineScope {
            val getApples = async {
                val (resp, time) = measureTimedValue {
                    getApples()
                }
                <http://logger.info|logger.info> { time.inWholeMilliseconds }
                resp
            }
            val getPotatos = async {
                val (resp, time) = measureTimedValue {
                    getPotatos()
                }
                <http://logger.info|logger.info> { time.inWholeMilliseconds }
                resp
            }
            getApples.await() to getPotatos.await()
        }


        send(doSomething(apples, potatos))...

    } catch(ex: Exception) {
        handle...
    }
}
j
It may depend on several factors. Are
getApples()
and
getPotatoes()
switching context? Are they using a single-threaded dispatcher? Also, where are you returning the value of the
coroutineScope
as a pair? It's not in the code you provided (there are no
await()
anywhere there)
a
In my case they dont switch context although I should be using
withContext(<http://Dispatchers.IO|Dispatchers.IO>)
since its a network request
Regarding second point I forgot (already editted)
j
Ok then given you're using
GlobalScope
(which doesn't have a dispatcher),
produce
should be defaulting to the multi-threaded
Dispatchers.Default
. If you can reproduce the problem in isolation (with nothing else eating the threads from the default pool) then I don't know what the cause could be. Do you have a minimal reproducible example?
Also, why the channel for a single value? It looks like you just need a suspend function here:
Copy code
suspend fun work(): SomeResult {

    try {
        val (apples, potatos) = coroutineScope {
            val getApples = async {
                val (resp, time) = measureTimedValue {
                    getApples()
                }
                <http://logger.info|logger.info> { time.inWholeMilliseconds }
                resp
            }
            val getPotatos = async {
                val (resp, time) = measureTimedValue {
                    getPotatos()
                }
                <http://logger.info|logger.info> { time.inWholeMilliseconds }
                resp
            }
            getApples.await() to getPotatos.await()
        }
        return doSomething(apples, potatos)

    } catch(ex: Exception) { // <-- this could catch CancellationException, and it's pretty bad. Try to narrow it down
        handle...
    }
}
Also, as mentioned, cancellation will be prevented by your catch-all block - please try to find a narrower exception to catch (what is the purpose of this catch block in the first place?).