I am using Galaxy Nexus(i9250) for development and testing. I noticed strange fact- sometimes when the total heap size is 64mb and allocated heap size is in and around 56-60mb, app crashes. But sometimes I noticed that even the memory shoots up to 80mb, app didn't crashes.
Initially I thought that maximum heap size for devices of the range nexus will be 64mb(now I realize it is wrong). So my question is what is the maximum heap size a device can use. If it is variable based on device, then on what factor heap size depends. I knew this is a common question. Could anyone guide me to the right answer. Thanks in advance!
NOTE: I didn't use LargeHeapSize = true; in my code
Considering , your app crashes every time giving "OutOfMemoryError"
DVM starts by allocating a small heap, after every garbage collection cycle it checks for free heap and compares it to the total heap memory and adds more memory in case that the difference is too small. So Heap can be increased or decreased at runtime as per Dalvik VM's requirement by OS.
So, when their is enough memory available in the system your app didn't get crashed when the memory shoots up to 80mb.(Assuming 64MB is not the hard limit of heap size)
Yes there is a hard limit on the heap size of every device which can be increased by using "LargeHeapSize = true" , but this might be too costly in terms of app performance as increased heap size is directly proportional to the time taken by the garbage collection process(as GC now have to traverse more objects inside bigger heap). So it is a big "NO,NO" until unless you exactly know what and why are you going for larger heap size.
on what factor heap size depends:
Heap size mainly depends on the resolution of the device you are
using, as more resolution needs larger images/bitmaps size to fit
in.(more pixels = needs more memory to incorporate)
Although, I didn't got through any written proof of this.. As per my
understanding Heap size also depends on the RAM size. Since, bigger
RAM size will allow more flexibility of multitasking and lesser
chances of getting the "OutOfMemoryError"
In case you needs to know exact amount of heap memory you can use, ActivityManager.getMemoryClass(). This method returns an integer indicating the number of megabytes available for your app's heap
ActivityManager.getLargeMemoryClass() for larger heap size
it is not clear that what device you are exactly talking about. It is also not clear how you calculated your heap memory.
I recommend you calculate your heap memory and available memory using this link
But if your app uses Native Memory, their are no restriction on that link.
I would only use the DDMS values as a guide to find memory leaks and memory allocation problems rather than some specific number given that you can target. Any Android application will be expected to run on a variety of devices so while you may have tuned your app for a 'Galaxy Nexus' you will want to be able to run on older devices, and test appropriately. See
#dongshengcn comment.
In addition to the links by #minhaz I would also read: Understanding Heap Size.
If you are trying to get a better understanding of memory management on Android then you should read Android Framework Engineer #hackbod's answer to: How to Discover Memory Usage of My Application in Android.
Related
I have created a simple game with libgdx. It's currently showing about 50mb heap size. I believe everything is being disposed, and I try not to create objects in redner loop. What is a safe heap size?
From developer.android.com
...each Android-powered device has a different amount of RAM available to the system and thus provides a different heap limit for each app. You can call getMemoryClass() to get an estimate of your app's available heap in megabytes. If your app tries to allocate more memory than is available here, it will receive an OutOfMemoryError.
I was reading about OutOfMemory error in Android, which comes when Android runs out of memory. Do we know that if my app consumes some x MB of memory then it will give OutOfMemory error? Does Android allocates a specific amount of memory to each app depending on the device and total physical memory?
For example, I've a device with 2GB RAM installed, 500MB is taken by OS, 500 MB is taken by other apps. Now my app has 1048MB of memory to run. So in this particular case when the system gives OutOfMemory?
Each app has some memory limit it can utilize for heap allocations. It differs for different phones (and you can increase it in manifest as well). This answer provides a great detail on this, giving specific figures for some models and settings.
As for how it is determined:
it tends to be based more on screen resolution, as higher-resolution screens tend to want to manipulate larger bitmaps, so Google makes heap size recommendations that, hopefully, device manufacturers will abide by.
CommonsWare
What you are looking for is best described by google itself Here
To get how much memory you can use you could do this:
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = manager.getMemoryClass();
Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
your OutOfMemory Exception caused by Heap size , not about the RAM .
To maintain a functional multi-tasking environment, Android sets a
hard limit on the heap size for each app. The exact heap size limit
varies between devices based on how much RAM the device has available
overall. If your app has reached the heap capacity and tries to
allocate more memory, it will receive an OutOfMemoryError.
here an useful link : https://developer.android.com/training/articles/memory.html
hope that help you :)
I'm testing my application's memory usage on the emulator. And the problem is that on the emulator the app heap is just growing and growing, just a little bit of resources are freed. And if no collections are made it will cause an OutOfMemory exception on big resolution screens.
I downloaded the Sony SDK and there is an emulator configuration for the Xperia Z that has 1080x1920 resolution and the default heap is 64MB. I think it's a small heap size for that resolution because my app uses 40MB only starting up. However on my phone it's using 15MB of 64MB (res. 540x960).
So this quite small heap size (might not be real?) + GC behavior is causing OutOfMemory quite fast.
On a real device (I've tested only on mine), GC is working very nicely, it's freeing resources that are no longer used, but I really cannot predict if that will work on other phones.
Should I ignore how GC is working on my emulator or might it be my app's problem?
Growing heap on emulator indicates that at some point you have memory leak.
They are very common when you send intents between different applications ( e.g select image from gallery) . Most of device can handle such leaks with no problem.
Another reason for heap to grow up: inefficient memory operations. That means at some time you are asking to much memmory ( e.g you selected 5M image from gallery, created inpuststream for it and keep in memory as bitmap, so you asking 15+M emulator will show just hight heap grow, but most of devices will show error).
If you see heap grows - analyse your memory usage and detect leaks. Link
If you dont detect anything strange you can almost safely ignore heap warning.
Note: heap show supplied space, not used.
Android has a heap size limit for each app. It could be 16M, 24M, 32M, etc.
My question is, will the size of the app itself is taken into account in the heap size limit?
For example, suppose the Android max heap size per-app is 16M. And my app is 10M bytes in size. Does it mean the OS will only leave the app 6M bytes heap after the app is running?
Thanks.
No. Your app is made of classes and drawable that will be loaded into memory at run time only when you use it. So for example let's say your app contains drawable that are for tablets, they are not loaded into the memory of a phone.
No, you'll have all 16M of heap.
Things that eat the heap are classes loaded in RAM, and objects created in RAM during the app session.
I see that the Heap Size is automatically increased as the app needs it, up to whatever the phone's Max Heap Size is. I also see that the Max Heap Size is different depending on the device.
So my first question is, what are the typical Max Heap Sizes on Android devices? I have tested memory allocation on one phone that was able to use a heap over 40mb while another gave out OutOfMemory errors in the 20's mbs. What are the lowest that are in common use and what are the highest that are on common devices? Is there a standard or average?
The second question, and more important one, is how to ensure you are able to use the resources available per device but avoid using too much? I know there are methods such as onLowMemory() but those seem to be only for the entire system memory, not just the heap for your specific application.
Is there a way to detect the max heap size for the device and also detect when the available heap memory is reaching a low point for your application?
For example, if the device only allowed a max heap of 24mb and the app was nearing that limit in allocation, then it could detect and scale back. However, if the device could comfortably handle more, it would be able to take advantage of what is available.
Thanks
Early devices had a per-app cap of 16MB. Later devices increased that to 24MB. Future devices will likely have even more available.
The value is a reflection of the physical memory available on the device and the properties of the display device (because a larger screen capable of displaying more colors will usually require larger bitmaps).
Edit: Additional musings...
I read an article not too long ago that pointed out that garbage-collecting allocators are essentially modeling a machine with infinite memory. You can allocate as much as you want and it'll take care of the details. Android mostly works this way; you keep hard references to the stuff you need, soft/weak references to stuff you might not, and discard references to the stuff you'll never need again. The GC sorts it all out.
In your particular case, you'd use soft references to keep around the things that you don't need to have in memory, but would like to keep if there's enough room.
This starts to fall apart with bitmaps, largely because of some early design decisions that resulted in the "external allocation" mechanism. Further, the soft reference mechanism needs some tuning -- the initial version tended to either keep everything or discard everything.
The Dalvik heap is under active development (see e.g. the notes on Android 2.3 "Gingerbread", which introduces a concurrent GC), so hopefully these issues will be addressed in a future release.
Edit: Update...
The "external allocation" mechanism went away in 4.0 (Ice Cream Sandwich). The pixel data for Bitmaps is now stored on the Dalvik heap, avoiding the earlier annoyances.
Recent devices (e.g. the Nexus 4) cap the heap size at 96MB or more.
A general sense of the app's memory limits can be obtained as the "memory class", from ActivityManager.getMemoryClass(). A more specific value can be had from the java.lang.Runtime function maxMemory().
Here are the "normal" (see below) heap sizes for some specific devices:
G1: 16MB
Moto Droid: 24MB
Nexus One: 32MB
Viewsonic GTab: 32MB
Novo7 Paladin: 60MB
I say "normal" because some versions of Android (e.g., CyanogenMod) will allow a user to manually adjust the heap limit. The result can be larger or smaller than the "normal" values.
See this answer for additional information, including how to find out what the heap size actually is programmatically, and also how to distinguish between the absolute heap size limit on the one hand and the heap limit that you should ideally respect, on the other:
Detect application heap size in Android
To detect what your present heap utilization is, you could try using the Runtime class' totalMemory() method. However, I've read reports that different versions/implementations of the Android OS may have different policies regarding whether native memory (from which the backing memory for bitmaps is allocated) is counted against the heap's maximum or not. And, since version 3.0, the native memory is directly taken from the application's own heap.
The iffiness of this calculation makes me think that it is a mistake to monitor your app's usage of memory at runtime, constantly comparing it to the amount available. Also, if you are in the middle of an involved computation, and find that you're running out of memory, it is not always convenient or reasonable to cancel that computation, and it may create a bad experience for your users if you do.
Instead, you might try preemptively defining certain modes, or constraints, upon your app's functional behavior that will ensure that it comes in under whatever your current device's relevant heap limits are (as detected during your app's initialization).
For example, if you have an app that uses a large list of words that must be loaded into memory all at once, then you might constrain your app so that for smaller heap limits only a smaller list of the more common words can be loaded, while for larger heap limits a full list containing many more words can be loaded.
There are also Java programming techniques that allow you to declare certain memory to be reclaimable by the garbage collector on demand, even if it has existing "soft" (rather than hard) references. If you have data that you would like to keep in memory, but which can be re-loaded from non-volatile storage if required (i.e., a cache), then you might consider using soft references to have such memory automatically freed when your app starts bumping against the upper limits of your heap. See this page for info on soft references in Android:
http://developer.android.com/reference/java/lang/ref/SoftReference.html