AsyncTask, must it take such a performance penalty hit...?

You're not the only one observing this behaviour. The slowdown by factor 10 is probably a result of Android using a Linux cgroup (scheduling class) for threads of priority BACKGROUND or below. All these threads have to live with 10% CPU time altogether.

The good news is you don't have to live with the Thread priority settings from java.lang.Thread. You can assign your Thread a pthread (Linux thread) priority from the definitions in android.os.Process. There, you not only have Process.THREAD_PRIORITY_BACKGROUND, but also constants to adjust the priority a bit.

Currently, Android uses the background thread cgroup for all threads with priority THREAD_PRIORITY_BACKGROUND or worse, and THREAD_PRIORITY_BACKGROUND is 10 while THREAD_PRIORITY_DEFAULT is 0 and THREAD_PRIORITY_FOREGROUND is -2.

If you go for THREAD_PRIORITY_BACKGROUND + THREAD_PRIORITY_MORE_FAVORABLE (aka 9) your thread will be lifted out of the background cgroup with the 10% limitation, while not being important enough to interrupt your User Interface threads too often.

I believe there are background tasks which need a bit of computational power but which are at the same time not important enough to de facto block the UI (by consuming too much CPU in a separate thread) and Android currently has no obvious priority to assign to these, so in my view, this is one of the best priorities you can assign to such a task.

If you can use a HandlerThread it's easy to achieve:

ht = new HandlerThread("thread name", THREAD_PRIORITY_BACKGROUND + THREAD_PRIORITY_MORE_FAVORABLE);
ht.start();
h  = new Handler(ht.getLooper()); 

If you want to go with AsyncTask, you can still do

protected final YourResult doInBackground(YourInputs... yis) {
    Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND + THREAD_PRIORITY_MORE_FAVORABLE);
    ...
}

but be aware that the underlying implementation may reuse the same Thread object for different tasks, for the next AsyncTask, or whatever. It seems that Android simply resets the priority after doInBackground() returns, though.

Of course, if your UI really consumes CPU and you want more power for your task at the same time, taking it away from the UI, you can set another priority, maybe up to Process.THREAD_PRIORITY_FOREGROUND.


AsyncTask runs at a lower priority to help making sure the UI thread will remain responsive.