2

I have a small code where I read a serialized file of 100 items in doInBackground, create a ArrayList and return from doInBackground. In PostExecute, I just copy the array list to my another ArrayList object which is tied to ListView adapter.

With this I was getting cpu usage 10-40% with a 10s timer.

I removed the async task and did doInackgrounf and postExecute work in ui thread serially, and I am always < 5% cpu in top command output.

SO is AsyncTask cpu hungry ?

Update below is code in myAsyncTask

class MyAsyncTask extends AsyncTask<String, String, ArrayList<Info>> {

    @Override
    protected ArrayList<Info> doInBackground(String... params) {

        ArrayList<Info> arr_list = new ArrayList<Info>() {
        };
        try {
            File f = new File(mainApp.getFilesDir(), "");
            String[] paths = f.list();
            ArrayList<String> delfiles = new ArrayList<String>() {
            };
            long n = 0;

            if (paths == null)
                return arr_list;

            for (int i = 0; i < paths.length; i++) {
                try {
                    long fname = Long.valueOf(paths[i]);
                    if (fname > n)
                        n = fname;
                    delfiles.add(paths[i]);
                } catch (Exception e) {
                    continue;
                }
            }

            lastFileNum = n;

            if (n > 0) {

                File fp = new File(mainApp.getFilesDir(), String.valueOf(n));
                FileInputStream fos = new FileInputStream(fp);
                ObjectInputStream os;

                os = new ObjectInputStream(fos);
                int count = (Integer) os.readObject();

                for (int i = 0; i < count; i++) {
                    Info ai = (Info) os.readObject();
                    arr_list.add(ai);
                }

                os.close();
                fos.close();

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return arr_list;
    }

    @Override
    protected void onPostExecute(ArrayList<Info> arr_list) {
        try{
            if (this.isCancelled()) {
                return;
            }
            if (arr_list != null && arr_list.size() > 0) {

                if (this.isCancelled()) {
                    return;
                }
                mainApp.Info_data.clear();

                for (int i = 0; i < arr_list.size(); i++) {
                    mainApp.Info_data.add(arr_list.get(i));
                }
                if (this.isCancelled()) {
                    return;
                }
                if (this.isCancelled()) {
                    return;
                }
                    adapter.notifyDataSetChanged();
            }
            if (this.isCancelled()) {
                return;
            }

        }
        catch(Exception e){

        }
    }

}

And called using matk.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, str);

2 Answers2

0

Well, several reasons I can figure out on top of my head:

  • Using AsyncTasks you're getting more CPU usage because you're spawning different threads, which by themselves need initialization and their JVM CPU time (keep in mind Java threads are managed by JVM).
  • You're concentrating the same work (all your tasks) in less time (by threading you're virtually executing all the tasks at the same time), so obviously CPU usage must be higher (energy is not created nor destroyed, only transformed).
m0skit0
  • 25,268
  • 11
  • 79
  • 127
  • But as my work is small (which is what <5% top) and timer is 10s. I believe AsyncTask must be finished very fast for my work load. Seems like this is not the case here –  Aug 06 '13 at 11:02
  • i have noticed that things take longer to do in a AsyncTask than on the UI thread, but its still better to use the async task as it allows the workload to be spread over more than 1 thread. – string.Empty Aug 06 '13 at 11:05
  • @Manish CPU usage does not account for the time of the task. I/O is very expensive in time and does not account as CPU time. I think this is really your bottleneck (you might consider pre-buffering from your external sources). – m0skit0 Aug 06 '13 at 11:07
  • @NicolasTyler That *longer* is negligible with the time gained threading. Usually tasks use most of their time waiting for I/O to complete rather than running. – m0skit0 Aug 06 '13 at 11:08
  • What I mean is that `for (int i = 0; i < count; i++) { Info ai = (Info) os.readObject(); arr_list.add(ai); }` will take most of the execution time and almost no CPU time because it will be doing I/O operations. – m0skit0 Aug 06 '13 at 13:02
0

You shouldn't be doing any form of long processing on the UI thread. This is bad for user experience and so bad for you as a developer, you should always offload any kind of prolonged processing.

What @m0skit0 said is not entirely true, "Using AsyncTasks you're getting more CPU usage because you're spawning different threads"

As of Android 3.0, Asynctasks run using .execute() do run off the UI thread but are run sequentially on a single "Asynctask thread" so if you spawn 10 asynctasks each waiting one second, it will take ten seconds to complete execution of all, not one as you'd expect. You have to EXPLICITLY tell Android to spawn them as distinct threads, see here for how to do that.

With regards to power consumption, best power efficiency, at least on ARM devices is to spin up the CPU cores to high speed but for a very short amount of time, then drop them back down to low frequency so they can sleep. Being able to condense execution into a short time frame is what you want to try and do to minimize power consumption.

--EDIT --

Executing using matk.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, str); will create unique threads for the asynctasks so they can run in parallel. To be honest that is a very hard question to answer without knowing what scheduler is being used to govern the kernel behaviour. I can agree that there is certainly large amounts of overhead in setting up asynctasks with android code being called. A better option would be to directly use java threads which have much less overhead, or iff the task is very VERY small, get rid of overhead completely and do on UI

The thing you have to remember is that Asynctask is a utility provided by Android to make your life as a programmer easier. As such, they have opted for usability and features over efficiency as the CPU utilization is showing. Personally, I very rarely use Asynctasks and manually thread myself as this gives me complete control over the behaviour and execution of my application.

To summarise, IMHO,

UI thread least overhead but MUST NOT be used for anything more than a few microseconds, this is enforced by android i.e if you try and run networking on UI it will crash Threading is most complicated, you have to manually configure and control thread lifecycle, and things like Handles are needed to perform any UI changes Asyctask is a nice easy to use utility provided by google which can make your life simpler, but, with the provided functionality comes a performance cost with the set up overhead

rcbevans
  • 7,101
  • 4
  • 30
  • 46
  • True. I don't know how he's actually using AsyncTask, and anyway, it still will consume more time because you have at least to queue the tasks for execution. And thanks for the power consumption behavior, I did not know this. But still you're not actually answering the question: why it does take more time one way and not the other? – m0skit0 Aug 06 '13 at 11:18
  • I have tried to add a little more information and briefly summarise – rcbevans Aug 06 '13 at 12:09
  • *"To be honest that is a very hard question to answer without knowing what scheduler is being used to govern the kernel behaviour"* I believe standard Linux kernel scheduler is being used. Android uses stock Linux kernel now IIRC. – m0skit0 Aug 06 '13 at 16:09
  • I don't believe this is the case as Android has considerations standard linux doesn't care about, e.g UI priority. found what seems a good explanation here: http://stackoverflow.com/questions/7931032/android-process-scheduling – rcbevans Aug 06 '13 at 16:13