Android app run times vary greatly

I’m making some very simple mods to one of the LunarG Vulkan API Samples (draw_cube) and running on the 970 board. Based on timestamps just before and just after a frame is drawn, different runs of the same app can take a very different amount of time to execute – sometimes different by a factor of 4 - like 75 msec vs. 300 msec. Also if I have a lot of draw calls in one frame, I start getting messages like this in the logcat: I/Choreographer: Skipped 59 frames! The application may be doing too much work on its main thread.
Any advice?

Three pieces of advice;

  1. 75-300 ms is too small of a window to make reasonable measurements. You need to stretch it out much longer to get a proper idea of the performance. In very short tests, anything can happen that can impact your results, like a GC hits, for example.
  2. Along the same line of thought, what’s going on with the CPU speed? Is it possible that the CPU frequency is a lot higher on the 75ms test than the 300?
  3. If it says you’re doing too much work on the main thread, then you should consider creating additional threads to do all your heavy lifting. Bogging down the main thread will cause your UI updates to have to wait for the big jobs to finish, and having ALL the work done on a single thread fails to take advantage of all the CPU cores you have available. Hikey970 is an 8 core processor, so why would you want to limit your work to a single core? Spread the work around, and keep the main thread for the UI.

Thanks for your reply. I switched over to a different code base and things are a bit better, but looking at frame rate over several minutes, there is still lots of variation - for instance 10fps to 20fps with an average of 15fps. What might be causing this? I’m wondering about GPU clock rate. Is there a way to lock the GPU frequency? Would that involve modifying any AOSP drivers?

I’m not sure if there is any way to lock the gpu speed. Any changes would be in the kernel, nothing to do with aosp.

What does the CPU load look like? Especially when the framerate is lower. Are you now distributing the work more evenly across more cores?
What does the workload look like? Is the work more complex when the framerate is lower?
Have you done anything to maintain constant or higher CPU speed? This will involve adjusting the cpu governor.

Thanks again for your help. Yes, the new app uses more than one thread. The average frame rate is lower (as expected) when I add GPU shader work. “dumpsys gfxinfo” confirms that the frame rate for this app has a large amount of variation, and it’s no reason - the workload is exactly the same in every frame. It does say there are slow UI threads, which I don’t understand either. Only 0.5MB of memory usage. I was trying to bring up the Android Studio profiler, but it spins forever; in the Run window it says “client not ready yet”. Also I don’t see Show CPU Usage in the Monitoring settings for some reason. Sorry for my noob issues.

I think that the next thing you need to do, is to track down the work being done on the UI thread, and make sure it isn’t. The UI thread is literally JUST for human interactions, like when you press a button on the screen.

When you start an application, the main thread of execution is the UI thread. You shouldn’t do anything on that thread except set up the UI and launch other (worker) threads. After the application is started, if you need to do any more work on the UI thread, you need to reconnect with that thread. Android’s typical UI elements have functions like “onClick” that automatically reconnect to the UI thread. Outside of that, you need to use runOnUiThread. But basically, that thread should be mostly sitting idle.

I do see that Android runOnUiThread is turned on. I am just using the straight Android Teapots sample. I am still stuck not able to get Android Studio’s profiler window to show anything. The app is running, I’m getting Logcat output, and there are no error messages.

runOnUiThread isn’t an on/off switch. It is a function you use to cause a block of code to be run on the UI thread.