My surfraceview is where the majority of my application is and I would like to reduce its lag, thus I have been told to take it off the UI Thread. Is it possible to run a SurfaceView in an AsyncTask?
While it is possible to draw into a SurfaceView from an AsyncTask it is not recommended. AsyncTasks can run in a serial queue so you would likely block other tasks. Instead just use a Thread. The SDK contains a sample app called LunarLander which shows how to do this.
Related
I am a mediocore android developer for years. I like android but there's a big problem; frame drops. Even the most powerful ones can stutter so frequently while IOS devices can run at constant 60fps. I just can't understand why. I want to know it. So first thing i did was watching an I/O presentation about performance. And i didn't really understand one thing. Why can't ui and render thread run at the same time ? Yeah i know the basics like render thread can't know what to render while ui thread is doing it's thing but why can't render thread render the frame before? You can see the video here:
https://youtu.be/9HtTL_RO2wI?t=491
And here's a diagram what am i asking for:
You get the idea. I don't know about low level things about android, can anyone explain this like i'm five.
Your process' main thread is responsible for the rendering of the frames that will be presented to the user, so you should keep the code running there as fast and light as possible. If you have to do some heavy processing or access any IO (network, sdcard, etc) that may impact on the fluidity of the application since the thread may be waiting for a response.
As a good practice you should start that IO access/heavy processing on another thread to run in background and let the system decide the priority to run it, if necessary is recommended to present some feedback to the user like a ProgressBar or something to indicate that something is being processed.
Also, the Render Thread need to know what to render before it does it, so the UI Thread have to process which information the app would like to present to the user.
As #JonGoodwin points out, they both run in parallel, but usually in two cores of the same processor, as nowadays phones have at least two cores. Both threads are run in CPU, where RenderThread sends rendering commands to the GPU. Notice that this is true since API 21 (RenderThread is what enables things like ripple effect).
The problem, though, is what #LucianoFerruzzi points out: usually poor code that does too many things in the UI thread (RenderThread is not accessible, at least not with standard mechanisms).
Also, see the following episode of Android Developers Backstage: Episode 74: Graphics
My app record video and use TextToSpeech->android.speech.tts.TextToSpeech.speak() at the same time.
If I run in high device like 4 procesor at 1.5 ghz works ok. But if I use in 2 procesor 1.1 ghz device ui thread go very slow, with freezing of 2-6 seconds.
I know that problem is in TextToSpeech because if I don´t use it and record video the ui thread works very fluently in low device. If I use TextToSpeech + record video ui thread don´t work and also voice freeze 1-2 seg.
Is there any way to improve performance of TextToSpeech.speak()?
You're using text to speech and video recording at the same time? And you're surprised its slow? Both of these take a non-trivial amount of CPU resources. Some things just take processing power. Try not using them at the same time and you'll get better results.
If you need to use them at the same time- try using synthesizeToFile first to write the sound clip to a file, then playing the soundclip while recording. This way you aren't trying to generate the phonemes at the same time as recording.
If you are referring to 'Cores' when you say 'processors'? It seems like you are doing activities that should run on 3 different threads.
the Main Thread should be free always. Try not to bog it down... ever!
Extend the AsyncTask class. AsyncTask will allow you to do something that will take some lengthy amount of time without blocking the main thread.
Since this is all running on a virtual machine (Dalvik, to be precise), we must assume that threading is also virtual. This means that if you run 3 threads on two cores, the Virtual machine will decide which threads get processor cycles, and sometimes that means sharing cores.
I would say that if you ONLY plan on doing two heavy things at once, for a lower end device, you could implement this using the main thread for video, and a second thread for TextToSpeech. This isn't ideal because it potentially blocks the main thread. But since Video is the smoother of the two, it would be the first choice candidate for running on the Main UI Thread.
Ideally, you want minimum three threads, leaving the main UI Thread primarily unblocked. You can poll for results from both threads to detect completion.
If you happen to have 4 cores, then creating three threads should likely have more distributed performance over the available cores.
Some docs to get you going:
Android Multithreading - a Qualcomm article, and
Android: AsyncTask
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.
I have an Android app with the camera configured to send its preview to a TextureView. In the onSurfaceTextureUpdated method of my SurfaceTextureListener I pull out the preview frame as a bitmap using:
textureView.getBitmap(existingBitmap);
It works fine, but takes a very long time (about 200-250 ms for a 720x1280 image). It seems like this should go much faster. Any thoughts on how I can improve the performance of this operation?
Using this command to get the preview generates a new bitmap from the preview, this is what is taking the application so long. My suggestion would be to perform this operation in a background thread explained in this link:
http://developer.android.com/reference/android/os/AsyncTask.html
It will also allow you to stack operations that require this operation to be completed first in the onPostExecute function.
This will allow the main UI thread to function and be responsive to anything else the user may need to do during this time.
This may not be the perfect answer you are loking for but hope it helps.
I recently had problem getting my physics to stop racing ahead of my rendering (they were on the same thread), After a few months, I resolved the problem in about 20 minutes by creating a new thread and putting by physics into that.
I find that having them completely separate from each other gives me far greater control and now my sprites are moving consistently across all screens at all frame rates.
My question is, is it 'better' to put logic and rendering in the same thread or separate threads? The latter seems better to me but does it cause any problems? (does if affect battery life for example?)
Thank you
Yeah it is definitely better to use multiple threads, especially if the calculation is non-trivial, in which case you could experience the dreaded "Activity Not Responding" dialog.
Something that I would definitely look into would be AsyncTasks http://developer.android.com/reference/android/os/AsyncTask.html . Essentially, you would perform all of your physics calculation in the doInBackground method(which is running in a background thread) and then periodically call publishProgress from within that(which will execute the 'onProgressUpdate' callback where you will do all of your rendering on the UI thread).
Actually using different threads for performing logic and rendering UI is really and always appreciated.and it correct also.
But to handle/manage the multiple thread is the harder responsibility for a programmer.
And as the threads also increase the battery consumption, so we should always use thread very carefully.
So the final outcome is use threads but carefully. because thread are useful is used optimally but dangerous is not used carefully.
You said...
"I'm using surfaceView which as I understand it, uses a separate thread for rendering (separate from the UI thread) - so I have 3 threads"
It sounds like you're assuming that by extending SurfaceView, you're automatically provided with another underlying thread for the Surface which is separate from the UI thread. I believe that this is NOT the case.
From the Android developer reference for SurfaceView: "One of the purposes of this class is to provide a surface in which a secondary thread can render into the screen."
The key word being can. You still have to spawn the separate thread yourself, the SurfaceView just makes it easier to draw to a canvas in a separate thread.
If you take LunarLander as an example, it has just two threads: the UI thread, and a manually-spawned 'LunarThread' in which the physics are updated and the canvas (via SurfaceHolder.lockCanvas()) is drawn to, as fast as possible, independent of the UI thread.