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
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.
The Application class in android provides the methods onTrimMemory and onLowMemory. I don't really understand them (of course other than the obvious linguistic meaning). How might I implement the method onTrimMemory? What does it mean to trim memory? I am obviously looking for detail technical answers. Beyond emptying caches (should I do that?), there seems to be something more specific meant by trimming. How is that done in android? Is it an OS thing? Is it a system level thing? Should I worry about it? I would really love to know how to override it.
What does it mean to trim memory?
Let go of objects, so they can be garbage-collected.
Beyond emptying caches (should I do that?)
Yes.
there seems to be something more specific meant by trimming
Not really. Android is saying "hey, um, things are getting a big snug on system RAM, could you cut back" for lighter levels, and is saying "gee, this is a real nice process you got here — it would be a shame if we had to terminate it" for more severe cases.
Bear in mind that with Dalvik (and I assume ART), garbage collection can actually reduce your process' working set size (a.k.a., amount of system RAM you are using), and so by reducing your heap usage, you make it a bit less likely that Android will terminate your process while you are in the background.
How is that done in android?
Let go of objects, so they can be garbage-collected. Mostly, this should refer to caches. Anything else, you should be letting go of as your app runs, based on business rules. So, for example, while you could terminate background threads in onTrimMemory() (and therefore let go of any objects only reachable via those threads), there are probably better/earlier points in time to terminate those threads, if they are not adding any value.
Is it an OS thing?
I do not know what you consider an "OS thing" to be.
Is it a system level thing?
I do not know what you consider an "system level thing" to be.
Should I worry about it?
If you are manually maintaining a cache that might consume a lot of memory, ideally yes.
If you are using a third-party library that has a cache (such as an image-loading library), see whether they register for onTrimMemory() themselves. If not, you might see if the library has some API for you to tell it to reduce the cache, then call that yourself from onTrimMemory().
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've been digging the web in quest of finding nice, androidish solution for this concrete problem, but havent found one, so here I am, posting my first question on StackOverflow.
To elaborate on my problem, I have a full-fledged aidl service, to which some other processes bind. My service will allocate some resources for each of process connecting to it, and I want to make this statement bold, the resource allocation is made for process, I make some kind of a session tracking, where getCallingPid() and getCallingUid() play a role of session identifiers.
So the problem here is that Android will never tell us if an application which was bound to us went away for some reason, so the system resources allocated for that destroyed process would be wasted away by being held by our service.
One solution that I found somewhat feasible is just to poll ActivityManager.getRunningAppProcesses and calculate set difference between current and previous snapshots, but this method looks really dirty.
Could anyone suggest some better method to do this? I'd be really grateful!
Thanks,
Giorgi
As far as I'm aware, Android won't tell you when processes are killed.
I suspect the only method is to get a list of running applications every x seconds or minutes, and keep track of the applications that way. I think this is what you already suggested in the question as well.
It's not pretty, but it's likely one of the only ways to do it.
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.