Multi-Core Android 101
Some of you may already be familiar with multi-core programming, so a lot of what I’m going to cover will be very familiar to you, but some Android developers may have never written for (or considered) how the multiple CPU cores available on CPUs such as Nvidias Tegra 2 chips (as rumoured to be in the Motorola Honeycomb Tablet) can improve the speed of their applications if the applications are written in a multi-core friendly manner.
If you’re not familiar with multi-core programming here’s a quick intro; The main thing to remember is that multiple cores mean multiple tasks can be performed at the same time (specifically one per core). I don’t mean the tasks appear to run at the same time, as happens with single core architectures like the Qualcomm Snapdragon found in many current devices (which switches between multiple tasks very quickly but has only one task running at any point in time), on a multi-core device multiple tasks are running at the same point in time (i.e. concurrently).
If you’re wondering what the advantage of a multi-core CPU is then you might want to think about this very simple example; You have an app which monitors updates from a couple of RSS feeds and performs a task for each update; While your application is running it becomes aware that both feeds have been updated and it needs to perform the task for each feed. On a single core device you could either run the task for first feed and then the task for the second or try to run both at once and rely on the OS to switch between the tasks for each feed; Either way the time taken in total will be roughly the same if the tasks are CPU intensive. On a multi-core device the tasks for each feed could run on different cores at the same time, and so the total time would be significantly less.
Even apps which aren’t designed for multiple cores can see an improvement in performance on a multi-core device; Android is constantly doing things whilst your application is running and on a single core device your application can get interrupted whenever Android needs to do something. With a multi-core device Android could do most of it’s work on another core and so your application gets interrupted less.
Using the cores
Java and Android already have a good framework for dealing with multi-core CPUs via Threads, AsyncTasks, and Services. All of these allow you to run tasks which can be run along-side other tasks and activities. With a version of Android which supports multiple cores the tasks can be shared out between the available cores to allow as many of them as possible to be running at the same point in time.
Each of them has benefits and draw backs, so I’ll provide an overview of each one;
Threads are part of Java and you can use them by either extending the Thread class or implementing the Runnable interface and passing it to a Thread instance. Due to Threads being part of Java (and not an Android specific addition) they are not aware of the constraints Androids has on certain operations. For example; If you start a Thread and try to interact with your user interface you’ll get an error. They also have no in-built limiter so you can try to start 1000 Threads for 1000 CPU intensive tasks but you’ll end up with a pretty unresponsive app and possibly an unresponsive device.
In most cases you only want to use Threads for reasonably short running tasks which aren’t associated with a UI action and don’t need to modify the UI. For tasks which interact with the UI an AsyncTask is a better solution, or, for longer running non-UI orientated tasks, a Service is a better choice.
AsyncTask is an Android addition to Java. It’s aware of the Android environment, offers methods for interacting with the user interface which won’t cause errors, and uses a mechanism known as thread pooling (using a ThreadPoolExecutor) to ensure that you don’t try to do too many things at once.
If you read the Android documentation the emphasis is slanted towards UI interaction, but there is nothing which says you must interact with your applications UI in an AsyncTask, you only need to start your AsyncTask from your applications UI Thread, so you can make use of the ability for AsyncTask to limit the number of concurrent tasks to ensure that you don’t start to bog down the device and keep your app reasonably responsive.
In most cases, when you have a task to perform that is closely related to the current activity using an AsyncTask is a good idea even if you don’t need to interact with the UI whilst the task is running.
Service is an Android Addition to Java and is ideal for longer running tasks.
You shouldn’t try to interact with an activities UI from a Service, but instead you can use Androids Notification mechanism to let the user know when the task has completed. This allows the user to go and do other things with their device and not become frustrated with your application because they have to keep your app on screen and wait for a long task to complete.
So now what?
Now you should have an understanding of how you can use Threads, AsyncTasks, and Services to split your application into sections which Android can spread around the available CPU cores. It doesn’t matter if there is only a single core (as in the Nexus S), or multiple (as in the Motorola XOOM tablet), the OS will distribute the tasks accordingly, but, if you don’t split your application up, Android probably won’t know it can split the tasks across the available cores and so your application won’t make the best use of the resources available.
The Android Developers Blog has a great post showing how to implement an AsyncTask.