I have created an Android app and I now want to make sure that it never goes above 16MB of heap usage.
Unfortunately for this task my device has a much bigger heap than the minimum of 16MB, it has at least 32MB.
When I track the allocations it just keeps allocating and allocating and seldom garbage collects which makes it hard to track down memory leaks.
I have tried to use various profilers but it is not easy.
Preferrably I would like to back and forth between activities and just see the heap go up and then back down so that there are no memory leaks but since the garbage collection is postponed until it is really needed this seems hard to do.
Is it possible to limit the heap size to 16MB on a 32MB heap size device for testing purposes?
The best way to do this is to use an Android Virtual Device, as you can configure the heap size in the Android emulator. It is in the advanced options when creating an AVD.
However if you must test this on a real device you can simulate having a smaller heap by creating a memory leak of heap memory on startup. Make sure you keep a strong reference to the object you allocate so it isn't garbage collected.
On a device with 32MB heap size, if you create a 16MB leak on startup this will leave the remaining 16MB of heap space for your application to use.
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'm having trouble finding good information about garbage collection in Android.
I don't really understand when you have a memory exception
Here's a question:
When I run my application and monitor it with the Android Device Monitor
I see that the allocated memory is 8 MB when the application has just started.
There's a button that creates an object each time it's pushed.
So when i keep pushing the button, the allocated memory grows until
it reaches the heap size. When the heap size is reached, the allocated
memory goes back to 8 MB but the heap has grown a little bit. After that,
this whole thing happens again and the heap keeps growing
Do i have a memory exception in this case? or is it normal that
the heap size keeps growing?
The heap size is sort of reserved memory you can use. The allocated memory is the actual memory in use.
When the allocated memory is nearing the heap size, and you see the allocated memory drop, objects are being garbage collected. The heap size will grow a bit, since you probably need more memory than currently reserved.
In the end, if you keep allocating memory without releasing it, the heap size and allocated memory will grow, until the system runs out of memory (for your application). At that point, an OutOfMemoryException will be thrown, and your app will crash.
Read Managing Your App's Memory | Android Developers for a deeper insight.
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.
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.
I have an application which creates a series of Bitmaps. I am holding these Bitmaps in SoftReferences, to avoid running out of memory. I would like the heap size to grow to the maximum 16MBs before it starts collecting my SoftReferences. However, the SoftReferences are collected very eagerly, prior to growing the heap to it's max. Is there anyway to force the references to be collected less eagerly? or to manually grow the heap to the max? Possibly a way to just start the application with 16mb allocated?
There is currently no way to modify the SoftReference collection behavior.
I'm not sure what you mean by "manually growing the heap to the max".
If these are instances of the Bitmap class (as opposed to some custom bitmap implementation), the pixel data is actually stored on the native heap, but uses an annoying "external allocation" accounting trick, which complicates the situation further. (Notably, the storage is freed by a finalizer, not the GC, and finalizers have to execute in a separate thread after the GC completes. It's possible to allocate Bitmaps until you run out of memory, and the GC has no way to release the memory before throwing an OOM error.)
It's a known issue in Andriod. When VM collects soft references, it either collects all or none, although it should collect 'some' and should not collect anything when there is plenty of free heap.
Check: http://code-gotcha.blogspot.com/2011/09/softreference.html