I'm using Android L for some heavily multi-threaded operations, using multiple ThreadPoolExecutors to run queues of AsyncTasks.
When my app goes to the background, I start seeing numerous logs for...
I/art: WaitForGcToComplete blocked for ##.#####ms for cause XXXXX
...with an occasional...
I/art: No such thread id for suspend: ###.
It seems clear that something is going on that's making GC take longer than expected. The log gets generated by art/runtime/gc/heap.cc deep in the AOSP. The secondary log message indicates it's probably related to my thread pools. What isn't clear is why this is only happening (i.e. getting logged) when the app is sent to the background.
I haven't seen any crashes yet due to this, but I have a lot more testing to go through. Has anyone out there run into issues coinciding with these logs?
Related
My application uses background thread to initialize some of the stuff required by main thread to load the hero activity. It has bunch of locks for synchronization. I am looking for a quick way to plot possible stack traces where main thread was waiting for lock held by background thread during app startup. I checked Thread Status Monitor. How do I debug this? What's causing it? but this is talking about point to time thread state where as I am looking for all such events that occurred during startup without knowing where those occured.
I do see that this information can be found by manually inspecting startup android profile trace and looking at various thread stacks to find these occurrences, but there is lot of data to go through. It would be great if the tool can just show me # of times main thread waited for lock held by other threads, total amount of time spent and places where it held those locks.
Q1) Do we know whether Android profiler can show this? I checked https://developer.android.com/studio/profile/cpu-profiler but couldn't find it.
Q2) If not, is there any other tool that can parse profiler exported trace and print this info?
Q3) If not, do you have any pointers on how to read exported trace file. It seems to be binary. I am going through https://github.com/JetBrains/android to figure it out. It seems to be using perfetto now, but I haven't been able to write any utility to read that data yet.
Update: I discovered that CPU profiling/Systrace option shows that my main thread does remain idle or waits for some resources, however it doesn't have information around what does it wait for or what methods run after it was idle for some time. Any pointers to how to marry java method traces and sys trace view?
Perfetto is able to show this information. Look for "Lock Contention" messages on the timeline for a given thread. It also prints the data which thread has obtained that lock.
I'm using DDMS to monitor threads in my app, and I see that my app has a bunch of native threads as shown in follow picture. And time to time, the number of native threads increased as user interact with my app, which cause my app sometime does not serve as I expect. Is there anyway to kill these native threads?
There is no such thing as a "native thread" on Android, although some people might use that to refer to threads that are not attached to the VM (which would also make them invisible to DDMS). The threads happen to be executing (or waiting) in native code at the time you did a thread dump, but may spend most of their time executing bytecode. (A list of Dalvik thread states is available here.)
The names of the threads suggests that they were created without being given an explicit name. The one thread with a name, NsdManager probably exists because you're using NsdManager, which "responses to requests from an application are on listener callbacks on a seperate thread" [sic].
It's possible that you can glean some useful information from a stack trace. In DDMS, double-click the thread to get a backtrace. On a rooted device, you can kill -3 <pid> to get a full dump, including native stack frames.
Killing arbitrary threads is not allowed, as they might be holding locks or other resources. If you can determine what is starting them, and that they are unnecessary, you can prevent them from being started in the first place.
1.Sometimes my app is running too slowly, and the log always print this error,although the app still continue running.
E/dalvikvm(17325): threadid=17: created from interp,name=auth
E/dalvikvm(17325): threadid=17: calling run(),name=auth
E/dalvikvm(17325): threadid=17: exiting,name=auth
E/dalvikvm(17325): threadid=17: created from interp,name=auth
2.The log prompted me this info:
I/Choreographer(17325): Skipped 227 frames! The application may be doing too much work on its main thread.
You'll have to profile your app to figure out where the slowdown is. Look at the running threads in the DDMS view and if that does not reveal anything, look into gathering a systrace.
As for your messages, the first group looks somewhat normal, you'll see the second fairly frequently if you're running on an emulator. On a real device, you'll see them also, but not as often. 227 frames does seem like an awful log though. Make sure you are doing all non-UI work on background threads. The systrace will help identify methods that are taking a long time.
I have downloaded the ADT bundle from android developer site and trying to start the emulator. But most of the time it is getting stuck in the starting process and other times it takes 5-10 mins to start.
I have checked the LOGCAT and there is this msg repeatedly coming : "wait for concurrent gc blocked"
Do anyone know how to solve this issue and and start the emulator normally?
Please note that I have a laptop with decent specs and I am not deploying any app in the emulator... I am just starting it plain.
Messages like this:
dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 6ms
indicate that thread A performed an allocation that couldn't be satisfied, so it tried to collect garbage. It discovered that a concurrent GC was already in progress in thread B, so it had to wait for that to finish.
Seeing a lot of those messages just means there's a lot of memory churn in that process. It also indicates that the system isn't simply stuck.
If you use
adb shell ps
and search for the process ID shown in the log message (use adb logcat -v threadtime), you can see what process is spinning.
you have infinite loops. track your looping canditions from the beginning
What are all the possible thread states during execution for native (C/C++) threads on an Android device? Are they the same as the Java Thread States? Are they Linux threads? POSIX threads?
Not required, but bonus points for providing examples of what can cause a thread to enter each state.
Edit: As requested, here's the motivation:
I'm designing the interface for a sampling profiler that works with native C/C++ code on Android. The profiler reports will show thread states over time. I need to know what all the states are in order to a) know how many distinct states I will need to possibly visually differentiate, and b) design a color scheme that visually differentiates and groups the desirable states versus the undesirable states.
I've been told that native threads on Android are just lightweight processes. This agrees with what I've found for Linux in general. Quoting this wiki page:
A process (which includes a thread) on a Linux machine can be in any of the following states:
TASK_RUNNING - The process is either executing on a CPU or waiting to be executed.
TASK_INTERRUPTIBLE - The process is suspended (sleeping) until some condition becomes true. Raising a hardware interrupt, releasing a system resource the process is waiting for, or delivering a signal are examples of conditions that might wake up the process (put its state back to TASK_RUNNING). Typically blocking IO calls (disk/network) will result in the task being marked as TASK_INTERRUPTIBLE. As soon as the data it is waiting on is ready to be read an interrupt is raised by the device and the interrupt handler changes the state of the task to TASK_INTERRUPTIBLE. Also processes in idle mode (ie not performing any task) should be in this state.
TASK_UNINTERRUPTIBLE - Like TASK_INTERRUPTIBLE, except that delivering a signal to the sleeping process leaves its state unchanged. This process state is seldom used. It is valuable, however, under certain specific conditions in which a process must wait until a given event occurs without being interrupted. Ideally not too many tasks will be in this state.
For instance, this state may be used when a process opens a device file and the corresponding device driver starts probing for a corresponding hardware device. The device driver must not be interrupted until the probing is complete, or the hardware device could be left in an unpredictable state.
Atomic write operations may require a task to be marked as UNINTERRUPTIBLE
NFS access sometimes results in access processes being marked as UNINTERRUPTIBLE
reads/writes from/to disk can be marked thus for a fraction of a second
I/O following a page fault marks a process UNINTERRUPTIBLE
I/O to the same disk that is being accessed for page faults can result in a process marked as UNINTERRUPTIBLE
Programmers may mark a task as UNINTERRUPTIBLE instead of using INTERRUPTIBLE
TASK_STOPPED - Process execution has been stopped; the process enters this state after receiving a SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU signal.
TASK_TRACED - Process execution has been stopped by a debugger.
EXIT_ZOMBIE - Process execution is terminated, but the parent process has not yet issued a wait4() or waitpid() system call. The OS will not clear zombie processes until the parent issues a wait()-like call.
EXIT_DEAD - The final state: the process is being removed by the system because the parent process has just issued a wait4() or waitpid() system call for it. Changing its state from EXIT_ZOMBIE to EXIT_DEAD avoids race conditions due to other threads of execution that execute wait()-like calls on the same process.
Edit: And yet the Dalvik VM Debug Monitor provides different states. From its documentation:
"thread state" must be one of:
1 - running (now executing or ready to do so)
2 - sleeping (in Thread.sleep())
3 - monitor (blocked on a monitor lock)
4 - waiting (in Object.wait())
5 - initializing
6 - starting
7 - native (executing native code)
8 - vmwait (waiting on a VM resource)
"suspended" [a separate flag in the data structure] will be 0 if the thread is running, 1 if not.
If you design a system app that has to work with threads in even more advanced way than usual app, I'd first start by examining what API is available on Android to access threads.
The answer is pthread = POSIX threads, with pthread.h header file, implemented in Bionic C library. So you have starting point for knowing what you can achieve.
Another thing is that Android doesn't implement full pthread interface, only subset needed for Android to run.
More on threads + Bionic here, and how they interact with Java and VM is described here. Also I feel that thread is actually a process, as my code uses setpriority(PRIO_PROCESS, gettid(), pr); to set new thread's priority - I don't recall where I got this info, but this works.
I assume that thread may be in running, finished or blocked (e.g. waiting for mutex) state, but that's my a bit limited knowledge since I never needed other thread state.
Now question is if your app can actually retrieve these states using available API in NDK, and if there're more states, if your users would be really interested to know.
Anyway, you may start by displaying possibly incomplete states of threads, and if your users really care, you'd learn about another states from users' feedback and requests.
Google:
Thread.State BLOCKED The thread is blocked and waiting for a lock.
Thread.State NEW The thread has been created, but has never been started.
Thread.State RUNNABLE The thread may be run.
Thread.State TERMINATED The thread has been terminated.
Thread.State TIMED_WAITING The thread is waiting for a specified amount of time.
Thread.State WAITING The thread is waiting.
These states are not very well explained - I don't see the difference between BLOCKED and WAITING, for example.
Interestingly, there is no 'RUNNING' state - do these devices ever do anything?