My app is composed of one fragmented activity and one service. Also a few receivers, connection to in-app billing (activity only) and a few other things.
I'm also using app-compat-v7 for fragments and action bar.
When I look at the app under running apps activity (just the service is running), it reports a whopping 27 MB. Memory analyzer shows that those are pretty much contained in resource cache: bitmaps, strings, reflection data, DexCache, etc. Note that service itself pretty much MAYBE needs a string or two plus a couple of bitmaps for notification and widget, but definitely not that much.
The service with all its classes, notifications and widgets takes only 120KB while the rest takes 27MB.
The package itself is 1.4MB without ProGuard.
I have searched repeatedly for a good solution, but nothing comes up that would help me with this.
How can I make my service consume less memory?
Related
Alright so I'm going to try to explain one problem at a time so you can understand the issues I'm having and hopefully someone will be able to tell me hoe to fix it. So my app runs perfectly but my users have been complaining of high ram usage and on average it runs any where from 120mb to 200mb IDLE which I agree isn't right so I went ahead and remembered a trick I used in a previous project and that was this line of code android:hardwareAccelerated="false". This removes about 10mb of ram per activity but I'm still sitting at about 90mb of usage so i went and looked a little harder and found this android:process=":ProcessName"> which takes my app from using 100mb to a mere 8mb of ram. But I'm facing a problem while doing this and that is the fact that I have a LocalBroadcastManager in a service activity that sends data to my MainActivity and when these two have different processes they don't communicate with each other, and if I combine them into the same process the usage spikes yet again. So I'm kinda stuck what to do at this point and I refuse to use the Android Memory debugger because it doesn't tell me jack crap about what my code is doing wrong. Quite literally I have 5 text views and an imageview inside of my MainActivity so I know its not that intensive by any means! If anyone needs code please let me know but I figured someone really didn't need to look at the code to answer this!
You wrote:
But I'm facing a problem while doing this and that is the fact that I have a LocalBroadcastManager in a service activity that sends data to my MainActivity and when these two have different processes they don't communicate with each other, and if I combine them into the same process the usage spikes yet again.
You can keep your Service in a separate process and bind to it from your app's first process, via IPC, inter-process communication.
See:
http://developer.android.com/guide/components/bound-services.html
There are different ways to do IPC. The Messenger option might be a good starting point for you:
http://developer.android.com/guide/components/bound-services.html#Messenger
From the documentation:
If you need your service to communicate with remote processes, then you can use a Messenger to provide the interface for your service. This technique allows you to perform interprocess communication (IPC) without the need to use AIDL.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I am writing this question not as part of any specific application, but as part of potential use for future applications. I know that the answers to this question can be very application specific, but I hope you will bear with me. I will convey my understanding as is, and hopefully you can help me by extending it. Surprisingly in vain, I have searched the web for a 'complete' overview and have not been able to find it. Any links to relevant pages are welcome obviously.
An android application by default runs in a single process. Each Activity or Service that you start will by default even run in the main thread. All actions by the user are queued by the Looper of the main thread, and the respective callbacks are handled in the main thread.
In order to provide concurrency, threads can be started in lots of different ways, single or in pools. There is not explicit need in this regard for multiple processes. Using multiple processes to allow the multiple cores of your device to work in parallel is not necessary since Threads can be run in parallel as well, maybe even your main thread? But perhaps it will be easier to actually achieve?
In order to let an Activity or Service work in a specific (potentially different) process you only set the android:process attribute in the Manifest file. So easy to implement?
The Android framework is specifically built for mobile devices, which typically have limited memory to go around with. Therefore processes can be killed under a variety of circumstances, clearly stated here. As long as you implement the lifecycle callbacks of Activities and Services, such as onStop or onDestroy, this should not give any real problems. But obviously compartmentalizing pieces of your application, by using multiple processes, could potentially keep more important things alive. For instance a background download Service could be kept alive (level 3 in importance), while the process with the initial Activity that started this Service, now in the background (level 4) could be freed for its resources. Furthermore the fact that you are isolating core features of your application might allow your device to make better use of its resources?
The Binder framework makes IPC fairly easy to handle, and is something you will use generally, regardless of actually using multiple processes. I think the main cost of having multiple processes to the application is the access to shared resources, or the sending of those resources between processes, excluding the additional resources required for forking a process from the Zygote. I wonder whether using multiple processes will actually force you to implement your application differently?
I think that conceptually the use of multiple processes will not increase ease of implementation?
To summarize the pros of multiple processes:
Isolation potentially gives more lifetime protection.
Compartmentalization gives the device more manoeuvrability in regaining resources.
Parallelization performance boost?
Cons:
A new process must be forked from the Zygote using resources
Within an application resources will need to be shared over multiple processes, which strain both the device and the perhaps application performance.
The main use case I can think of:
Use a foreground activity for any user interactions and run a continuously used bound Service to do useful synchronization that might outlive the session that the user has with your activity and/or application.
If you have any remarks on my understanding please state so (Note several question marks in my explanation). If you have any pros and/or cons to add please reply as well, I will add them to the list.
Using multiple processes to allow the multiple cores of your device to work in parallel is not necessary since Threads can be run in parallel as well, maybe even your main thread?
Live (non-blocked) threads will be run in parallel across multiple cores automatically.
But perhaps it will be easier to actually achieve?
I would consider threads easier than processes, but "easier" is generally an opinion.
For instance a background download Service could be kept alive (level 3 in importance), while the process with the initial Activity that started this Service, now in the background (level 4) could be freed for its resources.
Except that you wasted more resources by having the two processes in the first place, and keeping a service running for long periods of time is generally an anti-pattern.
The Binder framework makes IPC fairly easy to handle, and is something you will use generally, regardless of actually using multiple processes
Developers do not normally use Binder directly. Only those implementing bound services need it, and that is a fairly small percentage of Android apps.
I wonder whether using multiple processes will actually force you to implement your application differently?
Yes.
Isolation potentially gives more lifetime protection
IMHO, this is not a valid excuse for wasting RAM, CPU, and battery on multiple processes.
Parallelization performance boost?
Threads cover this.
The main use case I can think of
While there may be scenarios in which your use case actually is a net benefit to the user, it is far from certain. Given that you have to implement your app differently to handle multiple processes, using multiple processes is a last resort approach, not the sort of thing that you do routinely, IMHO.
I am doing some sort of benchmark for sqlite android. If I were to pre-load total of 120k before executing, will most device have enough memory? While the queries are executing, there are also other threads that are going on so memory might be the problem. How can I make use of the onLowMemory() method? There doesn't seem to be much examples on using that method. Thanks for any advice.
Making use of the method is as easy as overriding it in your Activity.
However, read the documentation carefully:
This is called when the overall system is running low on memory, and
would like actively running process to try to tighten their belt.
While the exact point at which this will be called is not defined,
generally it will happen around the time all background process have
been killed, that is before reaching the point of killing
processes hosting service and foreground UI that we would like to
avoid killing.
Applications that want to be nice can implement this method to
release any caches or other unnecessary resources they may be holding
on to. The system will perform a gc for you after returning from
this method.
I'm not sure (and the docs don't define) if "background process" includes AsyncTask instances and services, or just backgrounded applications, but I would guess so.
So, when this method is called (if it is ever called) the System has already killed everything it could (with lower priorities than your Activity) and now asks you to release any unnecessary resources in memory.
So, If you want to react on low memory, this might be too late already.
As for the general question if most Android devices would run out of memory, I don't know. The problem is, that devices vary a lot.
I also find it hard to imagine any real live situation, in which you would need to pre-load (or stack) 120k queries before executing. You could easily stack 200 and commit those, than stack another 200 and so on.
I'm not sure why you need to benchmark this, but please don't execute 120k queries for default entries in your applications database.
You can deliver your application with a filled database and copy it over from the assets/-folder. See android-sqlite-asset-helper
I've an application that has some foreground activities and also a service that updates some widgets.
The problem is that, as the process remains for the service, the memory from the other activities ,if they are opened, is never reclaimed.
Looking at that response from Roman Guy it seems that can be normal. But it is? For how much time android keeps the resources of not used activities? They can live for hours?
How can I know easily if the activities are leaked or are simple not reclaimed? I've tried with a program from AndroidMarket (FreeMemoryRecover) and it's cleared but I suspect that it kills the process and then restart the service...
Any help or suggestion will be heavily appreciated.
Note 1: I've investigated with a HeapDump + Eclipse MAT and I don't see strange references holding my activities
Note 2: I've already asked some questions about this problem:
Post 1
Post 2
The ability for Android to have multiple Activities, in different states, is a design principle as it allows users to quickly switch between activities without consciously having to shutdown whatever they were doing before. They can then quickly return to a previous activity.
If Android needs to pause an Activity, and quickly unpause it, it's going to need to keep the Activity's resources available to it.
If the memory is part of a terminated Activity, then it's leaked (very unlikely as the Linux kernel will reclaim all memory that was used when the process terminates), else it's either being actively used or is potentially about to be used.
What is that concerns you about this memory?
I would try the following :
Launch your app play with it to be sure it is fully loaded and use as much memory as it can.
Then hit the home button and launch the navigator, open techcrunch.com, lemonde.fr, youtube.com, dailymotion.com, launch a video from youtube, open up and play angry bird and last but not least open up a pdf document.
After that Android will have needed the memory back quite for sure. If your app is still there, you might have a problem, if its not, then everything went smoothly.
By the way, good on you to put so much concern in being a good citizen in AndroidLand !!
See my comment below your question.
See Romain Guy's post about Android memory leaks.
Specifically, look at the comment on the solution in the Launcher app. (look at unbindDrawables code here)
Use Context.getApplicationContext() whenever possible instead of your activity's context.
Are there pitfalls or the points to remember while programming for Android? I think the list will include topics on Multithreading, Persistent Storage, etc.
There are many things that could be said here.
The Android videos from Google I/O 2009 cover most of the aspects that should be kept in mind, when programming on Android. In fact, the http://android-developers.blogspot.com/ articles are the source, on which these presentations expand, and seeing them explained from some of the best Google engineers (and as a bonus you'll get a Q&A section) is a must for every Android developer, IMO.
Some of the things that could be mentioned:
Don't use floats, when you can achieve similar results with integers, because Android doesn't have native support for floating point values.
Use the debugging tools extensively, to optimize both performance and maintainability, and to avoid common pitfalls like ViewGroup redundancy in UI design, or unnecessary multiple calls to heavier methods (View.inflate(), findViewById(), setImageResource()).
Bundle your background service calls, otherwise you are waking up the OS unnecessarily and too often, while risking other services piggy-backing your call (which results in severely reduced battery life)
Prefer SAX-parsers over DOM-parsers, you lose time while implementing them, but you win time in your app's performance (and your device's availability)
Keep your UI manipulations on your UI thread, because the interface toolkit is not thread-safe
Keep in mind that orientation change destroys and creates your Activity again (I learned that the hard and painful way - this is how I started to follow the android-developers' blog)
...and many others.
Android Developers has good post about avoiding memory leaks due to keeping Context references. There are a lot of other interesting posts there too.
I wouldn't call them pitfalls per se, but always remember to take into account that this is not a computer that's plugged into a wall that can just be upgraded in various ways. You have an upgrade cycle of about every 2 years (the length of a standard mobile contract these days) and the hardware is (A) not the fastest and (B) static during that time.
Things to take into consideration:
1) How does the things your app does affect battery life? Are you splashing bright graphics all over the place? Running a lot of threads in the background? Services?
2) How much space does your application need to take up on the device? Is the information something that can be kept on a server and transmitted to the device for temporary use only when it's needed?
3) In regards to #2, is your app tolerant of bad/nonexistent network/mobile connections? How does it perform on the EDGE network vs 3G?
I'm sure you can come up with more but this is what I keep in mind while I'm writing my apps.