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.
Related
In Android, is Executors.newFixedThreadPool(size) going to consider CPU cores, or should I do it. And is it worth it?
If I want to load 50 images at once, I might be tempted to create a fixed thread pool with 50 threads, but:
context switching
number of available CPUs
might be factors that might make this even slower than maybe an executor using 2-3 threads, right?
So, is the newFixedThreadPool going to consider the CPU cores (and should it) or should I do it.
In Android, is Executors.newFixedThreadPool(size) going to consider CPU cores
No. You specify the number of threads. Android is not going to somehow scale that number of threads based upon CPU cores that the device has, let alone the number of CPU cores that are presently active.
should I do it
Probably.
And is it worth it?
Probably. In your case, you are heavily I/O bound, so having multiple threads is a good idea. However, 50 is likely to be too many (your cited context switching, plus just the heap space for 50 stacks). A typical sizing algorithm is (2 * number cores) + 1.
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.
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.
I am trying to speed up my app start-up time (currently ~5 seconds due to slow Guice binding), and when I run traceview I'm seeing pretty big variations (as high as 30%) in measurements from executions of the same code.
I would assume this is from garbage collection differences, but the time spent in startGC according to traceview is completely insignificant.
This is particularly aggravating because it's very difficult to determine what the effects were of my optimizations when the measurements are so variable.
Why does this happen? Is there any way to make the measurements more consistent?
I suppose you are starting profiling from the code rather than turning it on manually? But anyway even if you use Debug.startMethodTracing and Debug.stopMethodTracing from a specific point of your code you will receive different measurments.
You can see here that Traceview disables the JIT and I believe some other optimizations so during profiling your code is executed slower than without it. Also your code performance depends on overall system load. If some other app is doing any heavy operation in background your code will execute longer. So you should definitely get results that a slightly different and so start-up time couldn't be a constant.
Generally it is not so important how long your method executes but how much CPU time it consumes comparing to other methods.
Sounds like measurement is not your ultimate goal. Your ultimate goal is to make it faster.
The way to do that is by finding what activities are accounting for a large fraction of time, so you can find a better way to do them.
I said "finding", not "measuring", and I said "activities", not "routines".
To do this, it is only necessary to sample the program's state.
Many profilers collect a large number of samples of the program's state, but then they all fall into the same logic - they summarize, on the theory that all you want is measurements, and you don't really care of what.
In fact, if rather than getting summaries you could examine some of the samples in detail, it would tell you a great deal more about how the program is spending its time.
What's more, if on as few as two(2) samples you could see the program pursuing some goal, and it was something you could improve significantly, you would see a significant speedup.
This process can be repeated several times, and that's how you can really optimize it.
The process is explained in more detail here, and there's a use case here.
If you are doing any network related activity on startup then this tool can help you understand what is happening and how you might be able to optimize connections and caching. http://developer.att.com/developer/legalAgreementPage.jsp?passedItemId=9700312
I'm almost done with an app and I noticed that it runs at about 6-12% cpu when its in the background. Is this too much? What's a good amount our does it mostly depend on the app?
It does depend on the application. 6-12% CPU would be too much for a software like text editor. But it would not be too much for a web crawler and indexer crawling and indexing the web through 30 threads.
Whether it is too much or not also depends on the nature of other processes running on the system. While 6-12% CPU usage may not be threatening to other processes running on the system, but in case you are running a CPU intensive task say, sorting gigabytes of data that you need very urgently or indexing the web, you would want the CPU usage to go as high as 80% or even more and as a result you wouldn't want to run any other CPU intensive process on the server.
If you are concerned that you may be doing some wasteful operation without realizing it, you may want to use the profiler to see if you are spending too much time in code that you shouldn't. It may also be the case that your app requires 6-12% CPU for what it does, which shouldn't a problem if it's actually putting it to good use.