question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Coroutines Android Slow Launch Times

See original GitHub issue

Every Android developer knows that the time spent in Application.onCreate() is very critical. Therefore, I tried to speedup my app startup by offloading some initialisation work to a coroutine. However, my profiling results were surprising.

First Try: Dispatchers.IO

val start = System.currentTimeMillis()
GlobalScope.launch(Dispatchers.IO) {
    doWork()
}
val time = System.currentTimeMillis() - start
Timber.d("Launch time: $time")

I consistently saw times between 20-30 milliseconds.

Second Try: Dispatchers.Default

Same as the code above, but with Dispatchers.Default instead of Dispatchers.IO. This also took more than 20 milliseconds.

Third Try: Multiple Coroutine Launches

For the sake of profiling, I measured the launch time of multiple coroutines:

val start = System.currentTimeMillis()
for (counter in 1..5) {
    GlobalScope.launch(Dispatchers.IO) {
        Timber.d("Hello world from coroutine %s", counter)
    }
}
val time = System.currentTimeMillis() - start
Timber.d("Launch time: $time")

The average launch time is a little bit better, but it is still not so good. It took more than 50 milliseconds to launch those five coroutines.

Fallback to AsyncTask

I ended up using a classical thread instead of a coroutine. The thread is abstracted by android.os.AsyncTask:

class PrimitiveAsyncTask(val runnable: () -> Unit) : AsyncTask<Void, Void, Void>() {
    override fun doInBackground(vararg params: Void?): Void? {
        runnable()
        return null
    }
}

fun doAsync(runnable: () -> Unit) {
    PrimitiveAsyncTask(runnable).execute()
}
doAsync {
    doWork()
}

As you would expect, this piece of code took less than 1 millisecond to launch the AsyncTask.

My Setup

I use the following libraries: org.jetbrains.kotlinx:kotlinx-coroutines-core org.jetbrains.kotlinx:kotlinx-coroutines-android

As outlined below, I tested this with the versions 1.3.3 and 1.1.1.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:6
  • Comments:14 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
fkirccommented, Dec 28, 2019

I was able to implement a very simple workaround: Launch a dummy coroutine via an AsyncTask from Application.onCreate(), in order to initialize the coroutines library ahead of time.

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        preloadCoroutinesLibrary()
    }

    private fun preloadCoroutinesLibrary() {
        PrimitiveAsyncTask.doAsync {
            // Preload coroutine library asynchronously to avoid slow launches afterwards.
            GlobalScope.launch(Dispatchers.IO) {} // Dummy coroutine.
            GlobalScope.launch(Dispatchers.Default) {} // Dummy coroutine.
        }
    }
}
class PrimitiveAsyncTask(val runnable: () -> Unit) : AsyncTask<Void, Void, Void>() {

    companion object {
        fun doAsync(runnable: () -> Unit) {
            PrimitiveAsyncTask(runnable).execute()
        }
    }

    override fun doInBackground(vararg params: Void?): Void? {
        runnable()
        return null
    }
}

For me, this workaround is sufficient for the time being. Nevertheless, it might be advisable to further optimize the initialization code of the coroutines library.

3reactions
fkirccommented, Oct 3, 2020

I have now changed the setup of my experiments: Instead of measuring time in the Application.onCreate() of my Android app, I have written instrumented Unit tests. Although those Unit tests are still running on an Android device, the Unit tests do not launch any activity or service. As a result, the Unit tests have less noise and I expect a better reproducibility.

The results are not as bad as before, but still unsatisfying. Here are the launch times:

Single coroutine Dispatchers.Main: 5.252 milliseconds Single coroutine Dispatchers.Unconfined: 5.756 milliseconds Single coroutine Dispatchers.Default: 7.066 milliseconds Single coroutine Dispatchers.IO: 8.581 milliseconds

50 coroutines Dispatchers.Main: 5.801 milliseconds 50 coroutines Dispatchers.Unconfined: 32.751 milliseconds 50 coroutines Dispatchers.Default: 10.39 milliseconds 50 coroutines Dispatchers.IO: 51.269 milliseconds

Compare this with traditional threads:

Single AsyncTask: 0.125 milliseconds 50 AsyncTasks: 0.451 milliseconds

EDIT: I produced these results with the tests in this hello world application: https://github.com/fkirc/coroutines-performance-tests

Read more comments on GitHub >

github_iconTop Results From Across the Web

Kotlin coroutines slow start - Stack Overflow
Eventually after a new dozen messages the overhead will calm down and these times will become equivalent at about 15ms, but having nearly...
Read more >
Improve app performance with Kotlin coroutines
A CoroutineScope keeps track of any coroutine it creates using launch or async . The ongoing work (i.e. the running coroutines) can be...
Read more >
Android Startup Tip: Don't Use Kotlin Coroutines : r/androiddev
Nathanael explains why using coroutines during a startup is not always a good idea.
Read more >
Why are my coroutines slow? | The Dev Tavern
However, coroutines are also easy enough to misuse. One of the common mistakes that programmers make is accidentally injecting blocking calls ...
Read more >
Coroutines (likely) running far too slow on Android, what's the ...
public void BeginFade() · { · StartCoroutine(FadeIt_Image()); · } · IEnumerator FadeIt_Image() · { · yield return new WaitForSeconds(delay); ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found