My app makes a JNI call in an AsyncTask. The activity would crash (or somehow be terminated) on Android 4.0, but is ok on later versions.
Eventually, I tracked it down to a possible stackoverflow(!) in the JNI. One of my routines put 4K on the C stack (not recursive). Once I took this out of the stack, everything worked.
My question is, how much can generally be assumed, can it be configured or changed and does anyone know the reliable limits for various API versions.
My theory is that additional threads like AsyncTask are given a lot less than the main UI thread, which is why this doesn't often bite.
thanks for any info.
Related
Why my app freezes for some time on the first launch?
For an example animations of screen transitions or collapsing toolbar freezes on first showing time. If I kill the app completely and open it again there is no issues with performance. It happens even with release build type
If releasing a memory by killing your app helps to 'resolve' this issue, it a sign of memory leak. Do you use leak canary in your project (https://github.com/square/leakcanary)? If not, please add and test your app to figure out if there is a memory leak.
Freeze is also might mean some resource consuming task in the MainThread. Do you use a StrictMode? If not, please add it and see reports\crash -- it will help you to figure out if you or 3rd party library execute some time consuming operations in the MainThread. However even if your app passes StrictMode, you still can have other types of heavy operations, e.g. solving a complex differential equation, in the MainThread
Finally, Android Studio provides a good tools for app performance analysis. Please check them to find out less obvious performance issues.
There are many ways to freeze your app, the most common is to already have a heavy task run in long time at main thread, such as: load a large photo resource, call a restful api..etc
you should check more information at https://developer.android.com/topic/performance/vitals/tracking_jank
My customer raise a problem about our app which is the app is getting slower when using for long time, but our side cannot simulate the problem as we are not in their real working environment, we are not able to solve the problem before knowing the bug. anyone can help?
If it´s a issue that raises "by the passing of time", you should look for any task you might be running and repeating itself.
You should check the different types of functionalities you use.
For example, if your app it´s using a local database:
Look for unclosed cursors.
I/O work
If your are using animations:
Look for skipped frames
Complex view hierarchies
If using background tasks or threading:
I/O work
Unfinished threads
Increasing thread number
If using networking and Webservices:
Problems with your server database
Connection issues
Proxys
...
You could also use something like Firebase + Crashlytics to see if theres any warning raises but gets silently disposed.
Giving some more info about your app and what it does could be useful for elaborating more accurate solution.
A common source of slowing down apps is memory leaks.
on iOS what you can do is to activate Memory management flags on your target and keep a watch on the logs, you can also use Xcode Memory Graph and instruments leak tools to detect leaks.
on Android you can use tools like LeakCanary to be notified when leaks happens.
Once you have a leak detected you can inspect your code to identify the source and better manage memory.
#axierjhtjz mention lots of good starting points.
Does it occur on both iOS and Android, specific devices, vendors?
If it is mainly on a single platform (Android/iOS), on different devices and the main complaint is slowness over time, I would suspect the following:
Memory leak (maybe UI, fragments)
Data persistent data incremental over time or/and more IO operation over time.
If you unable to debug the problem on the customer site, I would suggest to add a remote real time monitoring capabilities over relevant parameters and logs.
A good tool we used in the past was TestFairy. maybe they have a free trial
I have been developing a much-revamped version of an earlier android application. So many additions and changes to the infrastructure, UI, and general organization were necessary that it was far easier to start from scratch with the new application and transplant some of the guts from the old one rather than trying to understand everything the previous developer wrote and incrementally perform smaller surgeries.
I have the source code from the previous developer, and it contains several activities, fragments, classes, etc. that I know likely are not being used in the final build. To make the transplant process as easy as possible, is there an easy way to find out which of the above components are simply not being used in the app?
A couple ideas that immediately come to mind are:
stepping through everything in a debugger and taking note of which components are used (this seems like a super inefficient and terribly tedious process)
add a log message to each component's onCreate/instantiation code and then run through the entire app (more efficient, but still a pain)
Is there an easy way to do this?
I am using ffmpeg compiled for android and works pretty acceptable for now, however sometimes errors appear (based on some android phone configurations) and the app simply force closes with this message:
Fatal signal 11 (SIGSEGV) at 0x00000001 (code=1), thread 20745 (AsyncTask #2)
The ffmpeg call is inside a try/catch; however, it does not seem to care.
So, how can I prevent this force close and show the user a message?
I'm afraid I can't do that. See also this answer which hints at why.
When ffmpeg dies, it takes with it your entire program. This is just the way things are. When programming in Java, you don't have to think about programs crashing in that manner, but when ffmpeg, which is written i C, dies, it can take down your entire Java program.
try/catch does not help, because ffmpeg does not know or care about Java exceptions. Your only solution while staying within a Java program, is to either find the bug which makes ffmpeg die, or find what triggers the bug and call ffmpeg in such a way that it does not crash. As pointed out by Alex Cohn, another solution is to run ffmpeg in another process, so that it can not take down anything else but its own process.
You can run ffmpeg not as a library, but as a separate executable process. This may be significantly less efficient, but in such setup your process may survive ffmpeg crash.
You can also setup your app such that it has Activity and Service that run in separate processes, see e.g. How to create an Android Activity and Service that use separate processes.
This allows for some watchdog mechanism, and more. I cannot tell without careful testing if this way can deliver better performance than running ffmpeg executable, or worse.
I'm trying to follow Android best practices, so in debug mode I turn all the following on:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all thread violations
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all virtual machine violations
Android now yells at me when I try to use any sort of file access or SQL in the main (UI) thread. But I see so many recommendations to use file access and/or SQL in the main thread. For example, the main activity should load default preference values inside onCreate() in case they haven't been set yet:
PreferenceManager.setDefaultValues(context, resId, readAgain);
Oops---that results in a file access on the first application execution, because onCreate() is called on the UI thread. The only way around it I can see is to start a separate thread---which introduces a race condition with other UI code that might read the preferences and expect the default values to already be set.
Think also of services such as the DownloadManager. (Actually, it's so buggy that it's useless in real life, but let's pretend it works for a second.) If you queue up a download, you get an event (on the main thread) telling you a download has finished. To actually get information about that download (it only gives you a download ID), you have to query the DownloadManager---which involves a cursor, giving you an error if you have a strict policy turned on.
So what's the story---is it fine to access cursors in the main thread? Or is it a bad thing, and half the Android development team and Android book authors forgot about that?
The only way around it I can see is to start a separate thread---which introduces a race condition with other UI code that might read the preferences and expect the default values to already be set.
Then use an AsyncTask, putting the setDefaultValues() call in doInBackground() and the "other UI code that might read the preferences" in onPostExecute().
To actually get information about that download (it only gives you a download ID), you have to query the DownloadManager---which involves a cursor, giving you an error if you have a strict policy turned on.
So query the DownloadManager in a background thread.
So what's the story---is it fine to access cursors in the main thread?
That depends on your definition of "fine".
On Android 1.x and most 2.x devices, the filesystem used is YAFFS2, which basically serializes all disk access across all processes. The net effect is that while your code may appear sufficiently performant in isolation, it appears sluggish at times in production because of other things going on in the background (e.g., downloading new email).
While this is a bit less of an issue in Android 3.x and above (they switched to ext4), there's no question that flash I/O is still relatively slow -- it will just be a bit more predictably slow.
StrictMode is designed to point out where sluggishness may occur. It is up to you to determine which are benign and which are not. In an ideal world, you'd clean up them all; in an ideal world, I'd have hair.
Or is it a bad thing, and half the Android development team and Android book authors forgot about that?
It's always been a "bad thing".
I cannot speak for "half the Android development team". I presume that, early on, they expected developers to apply their existing development expertise to detect sluggish behavior -- this is not significantly different than performance issues in any other platform. Over time, they have been offering more patterns to steer developers in a positive path (e.g., the Loader framework), in addition to system-level changes (e.g., YAFFS2->ext4) to make this less of a problem. In part, they are trying to address places where Android introduces distinct performance-related challenges, such as the single-threaded UI.
Similarly, I cannot speak for all Android book authors. I certainly didn't focus on performance issues in early editions of my books, as I was focusing on Android features and functions. Over time, I have added more advice in these areas. I have also contributed open source code related to these topics. In 2012, I'll be making massive revisions to my books, and creating more open source projects, to continue addressing these issues. I suspect, given your tone, that I (and probably others) are complete failures in your eyes in this regard, and you are certainly welcome to your opinion.