Can I have Async task run on different thread other than background - android

I have several Async tasks throughout an app I'm designing. Several times an async task will run very slowly. Examining the log file shows that the desired background operation isn't actually causing the delay. The delay is that the background thread is held up by the Garbage Collection (davlvikvm). I'm not totally sure why there is so much GC happening in my app, it's not particularly memory intensive (no videos, just basic lists and a few images), and the MAT tool doesn't show any egregious memory violators. Regardless, I'm looking for a solution to keep my app running quickly to avoid long delays for the user.
I have tried to force the GC to happen earlier to avoid it, but it still runs at these inopportune times. My new thought is to tell the async task to run on a separate independent thread, so that it is not held up by the status of the GC. Is this possible? Is there a better way?
Thanks

I don't have a specific solution to your problem, but no, running your workload on a different thread will not change the behavior of your application during GC.
GC essentially stops the whole VM while it's working. The Dalvik garbage collector (since Gingerbread) is designed to minimize the pause time, but it still stops the entire VM.
For a little more detail, see Does the DalvikVM Garbage Collector halt the whole VM?
As far as minimizing GC pauses, there does not need to be anything 'memory intensive' as you have described. More often than not, the problem is with creating a lot of smaller objects. The way to minimize GC pause times is to minimize the amount of garbage that you create.
The best way to minimize garbage creation is to pool (re-use) objects rather than creating them, throwing away the reference (allowing the to be GC'd), and then creating another one, etc.
For an approach to doing this, see, for instance, http://www.devahead.com/blog/2011/12/recycling-objects-in-android-with-an-object-pool-to-avoid-garbage-collection

Related

Under What Conditions Does ART Compact the Heap?

One of the touted features of the ART runtime in Android 5.0+ is heap compaction, to reduce heap fragmentation. A fragmented heap can get OutOfMemoryErrors a lot easier, as there may not be a single contiguous free block of memory big enough for your needs, even if the heap overall has enough free space.
I understand that this occurs when the app moves to the background, based on Google conference presentations and the like. However, the only statement that I can find on it in the documentation says:
Homogeneous space compaction is free-list space to free-list space compaction which usually occurs when an app is moved to a pause imperceptible process state. The main reasons for doing this are reducing RAM usage and defragmenting the heap.
It's unclear exactly what a "pause imperceptible process state" means, technically.
Suppose an app does not have any foreground activities at the moment. Is there anything that the developer might have done that might prevent heap compaction for that app's process? For example, does having a foreground service block heap compaction?
Putting the pieces of the puzzle together.
From what I can determine, ART will compact anything that is paused for 2-3 seconds and by paused it means not currently running in background, so activities, but not running services. It will also compact on the fly, or concurrently while the app is in the foreground.
Currently, the event that triggers heap compaction is ActivityManager process-state changes. When an app goes to background, it notifies ART the process state is no longer jank “perceptible.” This enables ART do things that cause long application thread pauses, such as compaction and monitor deflation.
Chet Hasse states:
Garbage Collection
ART brought improved garbage collection dynamics. For one thing, ART is a moving collector; it is able to compact the heap when a long pause in the application won’t impact user experience (for example, when the app is in the background and is not playing audio). Also, there is a separate heap for large objects like bitmaps, making it faster to find memory for these large objects without wading through the potentially fragmented regular heap. Pauses in ART are regularly in the realm of 2–3ms.
From what I can see any pause in the app is fair game for the ART GC.
I suspect the app needs to be paused completely of all services, etc for the compact to occur, as it's reallocating the memory addresses of the heap, and for this to occur, it cannot be changing. As this larger compact that is taken during the app pause and not on the fly is a dynamic rearrangement of the heap. The only changes that can be made in the smaller pauses is to re-route some addresses on processes no longer being used.
Though this is an educated guess, not definitive and I will endeavour to get more info.
The source code here should have the answer. They're using naming like InJankPerceptibleProcessState() and trying to wade through this, as you probably already have yourself.
Reading it, will update answer when/if I find the definite answer.
Homogeneous space compaction is free-list space to free-list space compaction which usually occurs when an app is moved to a pause imperceptible process state. The main reasons for doing this are reducing RAM usage and defragmenting the heap.
Source : https://developer.android.com/studio/profile/investigate-ram.html#LogMessages
Actually you can measure the idle time of an app by. Start the idle timer and stop if if there is any event captured in TextWatcher/OnKeylistner, if you app is in background and none of these events are called, it is good to be collected by GC.
Also this heap contraction is event based and priority based. Eg if there is never a scenario when user need memory, OS will not even do it.
As far as priority is concerned, for garbage collection, it looks for background apps with no background service, then app with background service and at last the foreground apps.

Worker Threads On Single Core Device

I have reposted my question from Android Enthusiasts here, as this is more of a programming question, and it was recommended.
Anyway. Here it is:
I am making an app, that changes the build.prop of key values for a ROM. However, Android often gives me an ANR warning, as I am doing all the work on the UI thread. On the Android documentation, it tells me that I should use worker threads, and not do any work in the UI thread. But, I am building this system app to go with a ROM for a single core device.
Why would I want to use worker threads, as isn't this less efficient? As, Android has to halt the UI thread, load the worker thread, and when the UI is used again, halt the worker thread and load the UI thread again. Isn't this less efficient?
So, Should I use worker threads (Which slows the UI thread down anyway) or just do all of my work on the UI thread *Even if the application UI is really slow)?
If your users were robots, your logic would make perfect sense. No context switching equals (very slightly) less overall computation time. You could benchmark it and see how much exactly.
However, in the present (and near future) your users will most likely be humans and with that you need to start thinking of psychology: A moving progress bar or responsiveness in general will give your users the impression that the the task is actually taking a shorter time than without any sort of feedback. The subjective speed is much higher with feedback.
There exist numerous papers on the subject of subjective speed, the first one I could find on the web has a nice comparison of progress bars in a video (basically, some bars seem to go faster than others, thus reducing the subjective overall wait time).
Use worker threads.
As you've said, doing everything on the UI thread locks your UI until the operation is completed. This means you can't update progress, can't handle input events (such as the user pressing a cancel button), etc.
Your concern about the speed of context switching is misplaced - this happens all the time anyway, as core system processes and other apps run in the background. Some quick Googling shows that context switching a thread within the same process is typically faster than a process-level context switch anyway. There is slightly more overhead introduced by creating the threads and then the subsequent context switches, but it's likely to be minute - especially if you only have the 1 thread doing the work. For the reasons I've listed above alone (UI updates and the ability to accept user input), take the few-millisecond overall performance hit.

Other processes call GC which slows down my game

I'm writing a real-time arcade game for Android >= 2.1. During gameplay I'm not allocating memory, to not seduce GC. Beacuse if GC invokes, it takes processor for 70-200ms. User see this as "oh no, that game is lagging...".
I checked LogCat. There are lots of GC_FOR_MALLOC or GC_EXPLICIT. But... not from PID of my process! My game is not causing them. They're caused because other processes, running in the background. Some wallpaper, widgets, radio, email, weather checking and other services...
I don't understand it entirely. When, for example wallpaper dissapears, its onPause() is called, I suppose. So, it should stop all its threads and certainly do not allocate any memory (or call System.gc()). Maybe it's wrongly implemented? I don't know. But there are some Android services, which are also causing GC from time to time... It's odd.
Is it a big Android <= 2.2 architecture flaw?
Android 2.3 introduces concurrent GC, which takes less time.
What can I do to ensure that my game will run smoothly?
First of all, the things which you see in LogCat will differ from one device to another. If you are certain the GC is not coming from your app, you have absolutely nothing you can do. You will always find the GC doing..something.
Make sure you keep YOUR code clean and very lite.
Plus, remember that generally speaking, in the presence of a garbage collector, it is never good practice to manually call the GC. A GC is organized around heuristic algorithms which work best when left to their own devices. Calling the GC manually often decreases performance.
Occasionally, in some relatively rare situations, one may find that a particular GC gets it wrong, and a manual call to the GC may then improves things, performance-wise. This is because it is not really possible to implement a "perfect" GC which will manage memory optimally in all cases. Such situations are hard to predict and depend on many subtle implementation details. The "good practice" is to let the GC run by itself; a manual call to the GC is the exception, which should be envisioned only after an actual performance issue has been duly witnessed.
I do not believe it is a flaw on Android <= 2.2. Is it happening on higher versions? Have you tested it?

In an android game should you allocate memory for resources in the ui thread or game thread

I asked a lead in to this question here. I want to know if it is recommended to read the android resources (in the res) folder on the ui-thread or on the game thread for a simple game (based off the lunar lander sample). I see in lunar lander that they allocate resources before starting the game loop. However that doesn't scale up very well if there are lots of resources. The answer to my previous question says that it is ok to read resources like bitmaps on the background thread. Now I want to know if this is the correct way to do things.
An alternate architecture would be to post a Runnable to the ui-thread from time to time and allocate resources then.
Does garbage collection come into play? I wasn't sure which thread GC runs on. But my guess is that it runs on the thread on which the object was allocated.
The answer to my previous question says that it is ok to read
resources like bitmaps on the background thread. Now I want to know if
this is the correct way to do things.
As per the doc here,
The BitmapFactory.decode* methods, discussed in the Load Large Bitmaps
Efficiently lesson, should not be executed on the main UI thread if
the source data is read from disk or a network location (or really any
source other than memory). The time this data takes to load is
unpredictable and depends on a variety of factors (speed of reading
from disk or network, size of image, power of CPU, etc.). If one of
these tasks blocks the UI thread, the system flags your application as
non-responsive and the user has the option of closing it (see
Designing for Responsiveness for more information).
So you can use a seperate thread to load resources on above mentioned conditions.
I think it depends on your needs and the size and number of resource and even if there are some other things to consider. For an instance, if you don't want your app user to navigate to the next screen until all your resources are loaded then using a thread may be helpful.
Garbage collection works in daemon thread. The daemon thread runs in the background.
Garbage collection comes into action when object becomes eligible for garbage collection i.e, when there are no live reference available or when memory becomes too low. Use this link to get to know about using tracking memory allocations and how to avoid frequent garbage collection to happen.

Stack memory in Android

I'm writing an app that has a foreground service, content provider, and a Activity front end that binds to the service and gets back a List of objects using AIDL. The service does work and updates a database.
If I leave the activity open for 4-8+ hours, and go to the "Running Services" section under settings on the phone (Nexus One) an unusually large amount of memory being used is shown (~42MB).
I figure there is a leak. When I check the heap memory i get Heap size:~18MB, ~2MB allocated, ~16MB free. Analyzing the hprof in Eclipse MAT seems fine, which leads me to theorize that memory is leaking on the stack. Is this even possible? If it is, what can I do to stop or investigate the leak? Is the reported memory usage on the "Running Services" section of android even correct (I assume it is)?
Another note: I have been unable to reproduce this issue when the UI is not up (with only the service running)
I'm writing an app that has a
foreground service, content provider,
and a Activity front end that binds to
the service and gets back a List of
objects using AIDL.
If that's all just one application, get rid of the AIDL and get rid of the content provider. Or, at least, don't use them yourself -- those are for other applications to use. They add overhead that you do not need for stuff inside your own VM.
...which leads me to theorize that memory is leaking on the stack. Is this even possible?
Not really. The main application thread stack is trivially small. Other threads have stacks that could get a lot bigger, but I'll be surprised if you are chewing up 42MB that way.
If it is, what can I do to stop or
investigate the leak?
Since you already did a "spike solution" of testing sans UI and determining that is OK, I'd slowly reintroduce the UI and see when you start getting the problem. One likely candidate problem area would be updating the activity from a background thread, so you might turn that off and see what happens.
Since your problem isn't in the heap itself, my guess is that your problem is tied to bitmaps or other things that have lots of off-heap RAM usage. The camera in your avatar is another hint in this direction. :-) Make sure you are recycle()-ing your bitmaps and such, and see if that helps any.

Categories

Resources