Is it bad to have many HandlerThreads alive, doing nothing, just waiting? - android

I use Handler in conjunction with HandlerThread all over in my Android project. I use most of them in Services. There, my Handlers backed by an individual HandlerThread with low priority get created in onCreated() and stopped in onDestroy().
Many of them just wait the whole time. E.g. they process stuff for a few seconds each five minutes.
In total my app has about 20 threads (half of them are HandlerThreads). So, is that an performance issue to have so many threads open? In Is it bad to have threads waiting in java? I learnt, that it should be correct. I just want to check, if that applies to HandlerThreadalso.

About 20? Probably not too bad. It may slightly decrease the performance of the kernel's scheduler, but so long as you don't hit an OS limit and aren't polling, idle threads don't take CPU. They can take memory though, so make sure not to hold on to any references you don't absolutely need on those threads.

Related

Android App high cpu usage and battery drain

I've been working on an android game for awhile now. I have the basic game implemented so now I'm going back and trying to optimize. It seems like the battery drain and CPU usage are too high for what I'm doing. I really only have my main thread and then all the drawing and updating is done on a separate thread.
Below is the code for the actual game thread that does updating and all the drawing. All of the actual code has been removed, what's left is what I've been experimenting with to figure out the abnormal CPU usage/battery drain.
So basically if I start the below thread with only an infinite while loop the app uses about 315mAh or about 9% of my phones battery in 30 minutes of use. If I start the thread with no code inside the run method so that it expires after one run through it uses roughly 70mAh or 2% of the phone battery in the same amount of time. The CPU usage also jumps from 2%-3% without the thread running to about 14%-15% when the thread running and just running the infinite loop.
To summarize it seems like running the thread with only an infinite while loop, that does nothing, increases the battery usage by 7% over 30 minutes. I don't see how this is possible and think I must be missing something. I'll keep working to figure this out but there's no more code to take out. If anyone has any suggestions or can provide some insight as to why this is happening I'd greatly appreciate it. Thanks in advance.
class InnerThread extends Thread
{
public InnerThread()
{
super();
}
public void run()
{
while(true){}
}
}
Loops with no delay or pacing are notorious for hogging CPU and battery. Think carefully about whether you really need to be processing continuously, or if once per frame, once per arbitrary time interval, or once each time some external event occurs would be sufficient. Try adding a small arbitrary delay in the loop, and you'll probably see an immediate improvement.
Many games use a main game loop. That's a searchable term. Basically, an endless loop performs some computations, draws a frame, then usually sleeps for some time. (See SystemClock.sleep() vs. Thread.sleep().) Your main loop could pass a frame number and timestamp to the rest of your code. You might compute the positions of moving objects every frame, but you could do more complex things like update the AI of your enemies only at certain intervals of time or frames. If you use a game engine like Unity, the main loop is still there, but you don't write it yourself. You just write the code that it calls every frame.
while(true) is a classical endless loop and probably not required in Java.
it does not even matter on which thread it runs, it's most likely draining the juice.
see Are "while(true)" loops so bad?
I went through and edited my code. Utilizing thread.sleep to limit the overall drawing and updating code to 60 frames per second. Also I made use of the Object.wait() and Object.notify() methods to reduce the unnecessary processing of the thread. I've seen huge improvements, thanks for the help, I really appreciate it. My problem was most definitely that I was wasting battery and CPU power processing nothing.

Context switching is too expensive

I am writing a video processing app and have come across the following performance issue:
Most of the methods in my app have great differences between cpu time and real time.
I have investigated using the DDMS TraceView and have discovered that the main culprit for these discrepancies is context switching in some base methods, such as MediaCodec.start() or MediaCodec.dequeueOutputBuffer()
MediaCodec.start() for example has 0.7ms Cpu time and 24.2ms Real time. 97% of this real time is used up by the context switch.
This would not be a real problem, but the method is called quite often, and it is not the only one that presents this kind of symptom.
I also need to mention that all of the processing happens in a single AsyncTask, therefore on a single non-UI thread.
Is context switching a result of poor implementation, or an inescapable reality of threading?
I would very much appreciate any advice in this matter.
First, I doubt the time is actually spent context-switching. MediaCodec.start() is going to spend some amount of time waiting for the mediaserver process to talk to the video driver, and that's probably what you're seeing. (Unless you're using a software codec, your process doesn't do any of the actual work -- it sends IPC requests to mediaserver, which talks to the hardware codec.) It's possible traceview is just reporting its best guess at where the time went.
Second, AsyncTask threads are executed at a lower priority. Since MediaCodec should be doing all of the heavy lifting in the hardware codec, this won't affect throughput, but it's possible that it's having some effect on latency because other threads will be prioritized by the scheduler. If you're worried about performance, stop using AsyncTask. Either do the thread management yourself, or use the handy helpers in java.util.concurrent.
Third, if you really want to know what's happening when multiple threads and processes are involved, you should be using systrace, not traceview. An example of using systrace with custom trace markers (to watch CPU cores spin up) can be found here.

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

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

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.

Optimal thread pool size in android

I got an app that got a lot of remote resource loading actions, scheduled runnables and other OS events handling.
I'm using a single executor service with cached threads.
I have no idea how many threads should I use for optimal performance and battery usage.
Is there a way to know?
Usually, you do not need to worry about number of threads affecting battery usage. Because if the amount of work is the same (lets say in terms of CPU instructions) there should be not much difference in battery drain if you do it on one thread or in parallel using 2 threads. You will have your result faster, but CPU will still execute almost same number of instructions.
As for performance gains, if thread consuming cpu 100% of a time, then having more threads, than amount of Cores wont make any performance difference, actually you will get a little bit less performance because of scheduling overhead.
You should define a metric to evaluate performance, and define what is "optimal" for you. It is really hard to say not knowing what software is doing exactly. And if there is no performance/battery issue right now, then there is probably no need to worry about it.
Your question cant have definitive answer because it is very broad.

Categories

Resources