I am frequently using gdbServer to debug a remote Android application. The area I have set breakpoints in is a shared library, written in c++.
Stepping through the code is extremely slow. Does anyone know why this is? My assumption is that the JNI calls to the library impose a large delay.
My assumption is that the JNI calls to the library impose a large delay.
When you are at a breakpoint, and execute step command in GDB, no JNI calls are actually happening (you are already in native code, and just continue until next line, or step into the next function, what's JNI got to do with it?)
Unfortunately, step could be slow even when executing natively; especially so for optimized code.
How could step command work? In theory, GDB could examine instructions for the current line, discover that there are no CALLs and JMPs, set a temporary break of the first instruction on the next line, and continue. That would be fast, but that's not how GDB actually works.
What it does instead is something simpler: it single-steps the processor, and at each instruction asks "am I now stopped on the same line I was last time I stopped?". If "yes", single-step again, until the answer is "no". You can observe this behavior by setting set debug infrun 1.
Depending on how many instructions your current line has, it could take a 100 single-steps to complete your step command. That can be slow with native debugging, it can become much slower still when using remote gdbserver, as every time single-step completes, GDB needs to ask gdbserver "where am I now". That's a lot of packets flying between GDB and gdbserver. You can observe these packets with set debug remote 1.
Thus the factors that
GDB remote protocol is "chatty",
that each packet needs to go to the device and back over a (relatively) slow link, and
that a single step may involve a 100 of these
combine to produce the very slow step executions you've observed.
A possible workaround is to avoid doing steps. Instead, set breakpoints, and examine program state at each. Eventually you'll get to a breakpoint that is "downstream" from the bug (i.e. the program is already in a bad state). Now set a new breakpoint somewhere "upstream" from that, and look at the state there. Using "divide and conquer" approach, you'll pretty soon zero in on the problem.
Related
Is there a possibility to debug the shaders (fragment and vertex) in an Android Application with OpenGL-ES 2?
Since we only pass a String with code and a bunch of variables to replace with handles, it is very tedious to find the proper changes that need to be done.
Is it possible to write to the Android Log, as in Log.d()
Is it possible to use break points and to inspect the current values in the shader calculations?
I am simply not used to write code with a pen anymore and that's what it feels like to code within the shader text code.
This is an old question but since it appears first in searches and the old answer can be expanded upon, I'm leaving an alternative answer:
While printing or debugging like we do on Java or Kotlin is not possible, this doesn't mean that it cannot be debugged. There used to be a tool on the now deprecated Android Monitor for letting you see a trace of your GPU execution frame by frame, which included inspecting calls and geometry.
Right now the official GPU debugger is the Android GPU Inspector, which has some useful performance metrics and will include debugging frame by frame in a future update.
If the Android GPU Inspector doesn't have what you need, you can go with vendor-specific debuggers depending on your device (Mali Graphics Debugger, Snapdragon Debugger, etc.)
No. Remember that the GPU is going to execute every program millions of times (once per vertex, and once per fragment), often with hundreds of threads running concurrently, so any concept of "connect a debugger" is pretty much impossible.
I am working with Google's Leanback library for Android TV and I am trying to figure out how to best listen for the buttons on the remote control (especially the ones that are not captured by the MediaSession).
For that reason I have a break point in BaseGridView.dispatchTouchEvent() and when I press one of the remote buttons the debugger does indeed jump to that point and shows me the usual debug information.
However, after a few (2-5) seconds the debug info disappears and is replaced by the message "Frame is not available".
In other places the debugger is working fine, so I was wondering whether the delay caused by the debugger is counted as ANR and the app is therefore force closed?
In any case, is there any way to get around this?
This message appears because u set too many breakpoints, and threads are waiting data from other threads, to settle this, you could cancel some breakpoints and waiting for the data to be ready...
the message "frames not available" means that no more frames are available for debugging.
The android studio help states clearly the purpose of the frame window and the frames within:
The Frames pane enables you to gain access to the list of threads of your application , export to a text file and customize thread presentation. For each thread, you can view the stack frame, examine frames, navigate between frames, and automatically jump to a frame's source code in the editor. You can select a thread via a the thread selector drop-down list on top of the pane. The status and type of a thread is indicated by a special icon and a textual note next to the thread's name.
So now that you have no frames available means all frames are closed for debugging. Might be due to app being force closed or misbehaving at that line in any way. Try debugging the statement after which this happens to get rid of this behaviour.
Hope it helps
When you get the message "frames not available" it means that no more frames are available for debugging. The frames are part of Android Studio's debugging which gives you access to the list of threads running in your application. It is the long list of processes you see in the debugging window. So what is happening is that Android Studio loses knowledge of the threads it had before you set the breakpoint when you are stepping out. This might be happening in your case because by default when you set a breakpoint, it stops execution of all threads. When you step out, the threads that follow rely on the threads before to work which is what closes the app. Since you are setting your breakpoint at getCurrentDetails, my best assumption is that it did not get the response from OKHttp in time since it is happening in a background thread. You can try two things to get it to work. First, try and right click on the breakpoint and change the breakpoint from pausing all threads to just that thread. This should allow OKHttp to get the response in time before being cut off. Or, shift your breakpoint further down and see if it works.
Having the same issue, restarting AS works for me.
File --> Invalidate Caches/Restart fixed the problem that I had.
Often I'm making some small changes, within one file, not touching 99% of the code. For example: small refactoring, tweaking parameters, layouts, animations. Changes which take couple of seconds. I just want to quickly experiment with many options and see what is the best.
There is a huge problem - recompilation and deploying time. I waste my time and lose my focus, which dramatically increases total tweaking time - from seconds of actual work to minutes (hours?), because of waiting and constant distractions. It's also annoying and doesn't encourage to experiment more.
I've heard about DyCI - Dynamic Code Injection, which does exactly what I want - "change your code and see the results right away". But, it's for iOS.
Is it possible to change the code and see the results right away on Android? How?
You could use incremental dex-ing
Full Incremental Builds – The new Gradle-based Android build system
has been designed for developer efficiency. Gradle’s support for
incremental tasks means you spend less time waiting and more time
coding.
from https://www.gradleware.com/android/gradle-the-new-android-build-system/
Also
What does the "Incremental Dex" option in Android Studio do?
If you're talking about hotswap, I think it's not possible with Dalvik VM (android's java virtual machine). This answer tells it too
I'd like to know the performance of my app, particularly the rendering time of video frames. I'm aware of DDMS in Eclipse->DDMS Perspective->System Information->Frame Render Time. However, as has been asked in this other question, the rendering information doesn't seem to show up even when you 'Update from Device' while the app is running.
After some research, I came across this command from this blog and this other one:
adb shell dumpsys gfxinfo <package-name>
However, when I run that command, it completes running right away and I get an output that looks like this, in part:
That is, I do not get more than one line of profile data (often the result is empty). What can I do to obtain more than one point of data in order to graph it? Or, what other alternatives should I consider to assess the rendering performance of the application?
The correct tool is systrace (basic docs, verbose docs). You will need a device that supports it, and will need root for some of the more useful bits.
You can see what every thread is doing, and much of the graphics stuff is instrumented. I don't think the video codecs themselves are typically instrumented, so you won't be able to see hardware codec decode times, but you can see the buffers move through the system.
Most of the interesting stuff will happen in mediaserver or SurfaceFlinger, so you won't see decoding / rendering activity appear in method profiling for your app.
I have a report that my app makes certain devices reset (reboot).
I have no idea how can an app possibly make a device reset (I don't use the Admin classes, and don't have that permission).
The app involves standard UI + JNI calls + some OpenGL ES 2 rendering.
My best guess is that a GLSL shader freaks out the device...
When a device resets it erases its LogCat buffer as well.
Any advice on what and where to look for?
Most likely you are right regarding that it's something using OpenGL. However, there is also some probability that it's something related to JNI (especially, if you are doing something beyond the basic calls).
I think the only way of actions is following:
gather info on which devices, OS version it happens
get a device to reproduce it or get in touch with a user who can do some testing for you
prepare a version which logs to a file (and dont' forget to flush a file after each line of log, else reset will kill a buffered logs)
wrap all suspicious places into logs