unexpected android system call makes smooth display of scrolling graphic stutter - android

I am currently writing an app that should display a real time measurement curve in a scrolling fashion (think ECG recorder or oscilloscope). An unexpected system call in the UI-Thread makes the display stutter.
The data rolls in via bluetooth. All works fine and the display is reasonably smoothly scrolling with an average update rate of 26 frames/s. But, nevertheless the display is stuttering remarkably.
I used traceview to get more insight and according to traceview the stuttering is the result of a call to android/view/ViewRoot.handleMessage which lasts 131 ms per call on average.
If I dig down further in traceview the cycles are burnt inside android/view/ViewRoot.performTraversals. 92% of these CPU cycles are consumed in mostly recursive calls to android/view/View.measure.
From there it gets complicated due to the recursive call structure. But I can find calls to the onMeasure() method of LinearLayout, FrameLayout and RelativeLayout. The onMeasure() method of each Layout type consumes about the same amount of CPU cycles. Which is very strange since in my activity I use only a simple LinearLayout with just 2 Elements.
I just see no reason on why a supposed re-layout of a LinearLayout with 2 Elements performs calls to non-used Layouts and takes a whopping 131 ms to do that.
Further info:
Platform HTC desire HD with Android 2.3.1.
I use a handler to perform the drawing in the UI thread.
The Layout is a simple LinearLayout with 2 Elements: a custom view and a textField.
The status bar is hidden with getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);.
The drawing is performed on each new block of data, which arrives approx. every 50 ms.
The drawing itself uses a canvas and is performant enough to keep up with the incoming data.
After that long explanation, here are the questions:
What is calling the android/view/ViewRoot.handleMessage? (the calls are relatively equal spaced every 850 ms and have no obvious link (no direct calls, number of calls and relative positions are not linked to the message handler for drawing) to any activity of my Activity)
How can I suppress the calls to android/view/ViewRoot.handleMessage or how can I make them faster (there are just 2 elements in my LinearLayout)
the calls to unused layouts first got me think of the status bar or some hidden activity (e.g. home screen), which may use such layouts. But how come those calls are part of the trace of my activity? As far as I understand the trace should only trace the active process. e.g. the calls of my service which produces the real time data is not part of the trace.
Is there any possibility to trace individual calls to some system components? When I zoom in in traceview I see this call sequence: toplevel -> android/os/Message.clearForRecycle() -> android/os/MessageQueue.nativePollOnce() -> android/os/SystemClock.uptimeMillis() -> com/htc/profileflag/ProfileConfig.getProfilePerformance() -> android/os/Handler.dispatchMessage() -> android/view/ViewRoot.performTraversals()
Off topic: Is there a possibility to export the data which is shown inside traceview (parents-children-CPU time etc.) other than a screenshot?

Ok, I found the reason for the long call to android/view/ViewRoot.handleMessage.
This was indeed caused by my application.
My App has 2 screens (Activities) one with a complicated Layout for status information and the other one the real time display of incoming data.
The data, which comes in over bluetooth contains mixed real time data and status data. When I switch to the real time Activity, I was stopping the status Activity with finish(); after starting the new real time Activity. Unfortunately this is not enough to stop also the message handler, which receives the new status information in the UI thread, and continued to update status data in an invisible and finished Activity. The relayout of this activity caused the stutter of the real time data.
This is now solved. The display scrolling is now reasonable smooth.
Thanks for your patience. May it be useful to anyone who stumbles on this Thread on stackoverflow.
jepo

Related

Android cold app start: How to optimise time to Application.onCreate?

My current app takes for a cold start ~8 seconds and I want to optimize that.
For that reason I added a log entry in my Application onCreate (Application, not Activity)
override fun onCreate() {
Log.d("myTag", "Calling Application onCreate()")
....
}
When looking in the logs and measuring the time, I found out that the above mentioned 8 seconds consist of the following:
Tapping app icon => Application.onCreate = 4 seconds
Application.onCreate => my Activity visible = 4 seconds
I know I can optimize the time from Application.onCreate() onward. It's my code and I can speed this part up.
But how can I optimize the time the system needs until my Application.onCreate is called?
Thanks!
Sounds like a great usecase for systrace. I usually use (at least) the gfx, input, view, wm, am, res, dalvik, bionic, and sched categories. A -b 10000 to ensure a sufficient buffer size doesn't hurt.
You'll get an html file which can be loaded in a browser, or opened through Chrome/Chromium's built-in chrome://tracing page.
At the top, you'll see CPU details like usage% and which thread is running at which time. Then, you'll see all the processes on the device, containing nested colored blocks ("segments") with information about what's currently going on. At the top of each thread, there is a small colored bar: white is "sleeping" (this includes waiting on a mutex), blue is "waiting for CPU", green is "running on CPU".
If there is a segment that seems interesting but you don't understand the exact meaning of, a search for the text at https://cs.android.com/ can be useful.
In any case, my guess is that you either have some library linking or ContentProviders that take time before Application.onCreate. Both of those would be visible in a systrace. And if my guess is wrong, you'll likely find something else. Good luck! :)
(it could also be class initialization... it'll be interesting to hear what you find!)

Executing a sequence of time-consuming Android UI updates without hanging UI

Disclaimer: it's possible I'm going about this in completely the wrong way & trying to solve the wrong problem.
I'm writing an Android app that uses Google Maps to show cloud cover over a 1km square area by adding a 1km-diameter circle to the map for each area with detected cloud cover via the following (probably naive) method:
CircleOptions options = new CircleOptions();
// ... set the center, radius, fillColor, strokeWidth, and strokeColor...
mMap.addCircle(options);
If there are just a few dozen circles added to the map, the performance is fine. If half the state of Florida is covered with clouds, the program chokes & hangs the UI for 5-30 seconds while it makes a few thousand calls to addCircle()
AsyncTask won't work here, because the time-consuming jobs are the calls to mMap.addCircle(), which HAVE to be made from the UI thread. I actually tried using doInBackground() to populate an array of CircleOptions, then iterated through it in onPostExecute() to make the calls to addCircle()... and as expected, it made absolutely no difference whatsoever to the app's performance (I think populating the CircleOptions array in doInBackground() shaved a whopping 18ms from the execution time on the UI thread).
In Unity, I could just use the Update() lifecycle method (which gets called once per video frame) and make 20-50 calls to addCircle() at a time before exiting to give it time to metaphorically go up for air and service the UI before the next batch. But AFAIK, Android Activity has no equivalent to this. You can do things that don't require UI changes in a background thread, then update the UI when it finishes... but there doesn't seem to be any explicit provision in Android for gracefully spreading multiple time-consuming UI updates across multiple frames.
So... DOES Android have some way to gracefully batch time-consuming UI updates across multiple frames a-la-Unity? Or is there a better way to render circle overlays onto a Google Map that can scale gracefully and handle thousands of such circles without choking?

Taking advantage of multithreading with openGL

Talking in context of a game based on openGL renderer :
Lets assume there are two threads :
that updates the gameLogic and physics etc. for the in game objects
that makes openGL draw calls for each game object based on data in the game objects (that thread 1 keeps updating)
Unless you have two copies of each game object in the current state of the game you'll have to pause Thread 1 while Thread 2 makes the draw calls otherwise the game objects will get updated in the middle of a draw call for that object ! which is undesirable!
but stopping thread 1 to safely make draw calls from thread 2 kills the whole purpose of multithreading/cocurrency
Is there a better approach for this other than using hundreds or thousands or sync objects/fences so that the multicore architecture can be exploited for performance?
I know I can still use multiThreading for loading texture and compiling shaders for the objects which are yet to be the part of the current game state but how do I do it for the active/visible objects without causing conflict with draw and update?
The usual approach is that the simulation thread after completing a game step commits the state into an intermediary buffer and then signals the renderer thread. Since OpenGL executes asynchronously the render thread should complete rather quickly, thereby releasing the intermediary buffer for the next state.
You shouldn't render directly from the game state anyway, since what the renderer needs to do its works and what the simulation produces not always are the same things. So some mapping may be necessary anyway.
This is quite a general question you're asking. If you ask 10 different people, you'll probably get 10 different answers. In the past I implemented something similar, and here's what I did (after a long series of optimisation cycles).
Your model-update loop which runs on a background thread should look something like this:
while(true)
{
updateAllModels()
}
As you said, this will cause an issue when the GL thread kicks in, since it may very well render a view based on a model which is half way through being rendered, which can cause UI glitches at the best case.
The straight-forward way for dealing with this would be synchronising the update:
while (true)
{
synchronized(...)
{
updateAllModels();
}
}
Where the object you synchronize with here is the same object you'll use to synchronize the drawing method.
Now we have an improved method which won't cause glitches in the UI, but the overall rendering will probably take a very severe performance hit, since all rendering needs to wait until all model updates are finished, or vise versa - the models update will need to wait until all drawing is finished.
Now, lets think for a moment - what do we really need to be synchronizing?
In my app (a space game), when updating the models, I needed to calculate vectors, check for collisions and update all the object's positions, rotations, scale, etc.
Out of all these things, the only things the view cares about is the position, rotation, scale and a few other small considerations which the UI needs to know in order to correctly render the game world. The rendering process doesn't care about a game object's vector, the AI code, collision tests, etc. Considering this, I altered my update code to look something like this:
while (true)
{
synchronized(...)
{
updateVisibleChanges(); // sets all visible changes - positions, rotations, etc
}
updateInvisibleChanges(); // alters vectors, AI calculations, collision tests, etc
}
Same as before, we're synchronising the update and the draw methods, but this time, the critical section is much smaller than before. Essentially, the only things which should be set in the updateVisibleChanges method are things which pertain to the position, rotation, scale, etc of the objects which should be rendered. All other calculations (which are usually the most exhaustive ones) are performed afterwards, and do not stop the rendering from occurring.
An added bonus from this method - when you're performing your invisible changes, you can be sure that all objects are in the position they need to be (which is very useful for accurate collision tests). For example, in the method before the last one, object A moves, then object A tests a collision against object B which hasn't moved yet. It is possible that had object B moved before object A tested a collision, there would be a different result.
Of course, the last example I showed isn't perfect - you will still need to hang the rendering method and/or the updateVisible method to avoid clashes, but I fear that this will always be a problem, and the key is minimizing the amount of work you're doing in either thread sensitive method.
Hope this helps :)

How do I measure FPS of an android application that uses TextureView? (Am using OpenGL)

I have an infinite loop in my Render Thread. I tried measuring assuming that every call to eglSwapBuffers draws a new frame, but that is giving me results like 200 fps, which is not possible, right? The refresh rate cannot exceed 60?
Now I am doing the same thing but also using surfaceTexture.getTimeStamp() of the surfaceTexture of the SurfaceView. I consider a frame as having been drawn only if the timestamp returned in the previous iteration is not the same as in the current. Is the an acceptable way to measure? This is showing 50-55fps when I do no drawing. ie the loop has only eglSwapBuffers() and the getTimeStamp calls.
The surfaceTexture.getTimeStamp() seems to be giving the correct result. I tested it by adding up all the differences between results returned by consecutive getTimeStamp() calls and it is equal to the total time the code ran for. This indicates that no frames are being left unconsidered etc.
Another solution I found is this Android app. I do not know how it works but it is giving approximately the same results as the above method.

How to interrupt GLSurfaceView rendering phase and start a new one?

Hi Android Developers,
What is the best way to interrupt a current rendering phase of GLSurfaceView and start a new one when mode is equal to "Render_when_dirty"? I artificially stop rendering in "onDraw" method by checking a flag and returning from actual rendering method which is called in "onDraw" method; then, in main thread's context i call "requestRender()" to refresh the scene. However, due to a reason that i am not aware of, some of the intermediary old frames are displayed for a very very short period of time(on the other hand, they endure for so long period of time that users can realize the transition); before actual scene is rendered by opengl es 2.x engine. It doesn't affect anything at all; but troublesome to be fixed. What do you suggest?
P.S. Throwing InterruptedException within onDraw method is useless due to the destruction of actual rendering thread of GLSurfaveView.
Kind Regards.
When you say some of the old frames are drawn - do you mean part of the frame that is drawn is old or multiple calls of onDraw() still lead to some of the old information being shown on the display.
There are a few things I can see happening here. If you have a onDraw() like this:
onDrawFrame(){
... stuff ...
if (stateVariableSet)
return;
... stuff ...
my understanding is that when the function is done being run, that the back/front buffer get swapped and drawn. One thing that could be happening here is that you see a few calls of onDrawFrame() being rendered while you try to update the state/State variable.
On the other hand, if you have something like this:
onDrawFrame(){
... stuff..
semaphore.acquire(); // lock the thread waiting for the state to update
... stuff ...
then the things that have been drawn before the lock will be stale (for that frame only though - at least that's what I'd anticipate).
Also are you running on a multi-core system?

Categories

Resources