How to know how much ram size my app needs? - android

I am new to android and my app sometimes resulted in an outOfMemoryException. Therefore I have to check how much ram my app is using and try to reduce it.
Two questions:
How to know the ram size that my app is using?
Normally, what is the safe threshold for an app's ram size so that it would not cause an outOfMemoryException ?
Thanks a lot for your help!

Check out Android Studio's in-built memory monitor. that you will find under
Android Monitor > Monitors
and for the second part of your problem you can use ActivtyManager class' getMemoryClass () method.
from the android doc..
Return the approximate per-application memory class of the current device. This gives you an idea of how hard a memory limit you should impose on your application to let the overall system work best. The returned value is in megabytes; the baseline Android memory class is 16 (which happens to be the Java heap limit of those devices); some device with more memory may return 24 or even higher numbers.

Check that the image size is smaller than the available memory before attempting to load it. So the most efficient way to handle OutOfMemoryException is to architecture your application in such a way that it never attempts to load lots of data into memory in order to avoid the exception.
Before loading images into memory compress your images using
Bitmap original = BitmapFactory.decodeStream(getAssets().open("1024x768.jpg"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
original.compress(Bitmap.CompressFormat.PNG, 100, out);
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
Log.e("Original dimensions", original.getWidth()+" "+original.getHeight());
Log.e("Compressed dimensions", decoded.getWidth()+" "+decoded.getHeight());

1.How to know the ram size that my app is using?
This question quite hard to answer. Different type of apps requires different memory.
2.Normally, what is the safe threshold for an app's ram size so that it would not cause an outOfMemoryException?
Different devices have different threshold. You can normally use
Runtime rt=Runtime.getRuntime();
long maxMemory=rt.maxMemory();
Log.i("maxMemory:",Long.toString(maxMemory/(1024*1024)));
to see a size of maxMemory you can use. But this is not exactly.

Related

How to know app going to reach max heap memory?

I am making Image gallery app with various types of image in term of resolution and size.
As per my observation, when app try to load large image its throws OutOfMemory.
How can i prevent app from OutofMemory?
Is there any way to get notification before app get crash because of OutOfMemory?
How can i know app going to reach heap capacity?
How can i prevent app from OutofMemory?
Allocate less memory. For example, with images, use things like inSampleSize on BitmapFactory.Options to only load into memory what you need, not the whole image.
Also, if your images will be the same resolution, use inBitmap to reuse already-allocated Bitmap objects, rather than let them get garbage-collected.
Is there any way to get notification before app get crash because of OutOfMemory?
No, because you are not out of memory.
How can i know app going to reach heap capacity?
You are not reaching "heap capacity".
Dalvik's garbage collector is a non-compacting (or non-moving) garbage collector, and so over time your heap becomes fragmented. OutOfMemoryError means that you are trying to allocate something for which there is no single free block big enough. I wrote a blog post that explains this a bit more and explains how the new ART runtime will help in this regard in the future.
getMemoryClass() gives you an estimation of how much memory you have available in your application.
getLargeMemoryClass() gives you an estimation of the large heap size you can allocate to your application.
So debug your application first to know where does it throw an exception exactly (line) then add logs to see how much memory you got.

How much memory your app will take up when develop the android app?

Sometimes we encounter the memory issues,such as the OOM problems.And We inevitably have to manage the memory.Android has set a limit to the memory used bye each app.The maximum limit probably is the 32Min the early versions of android,such as 1.5,1.6,2.1.
Android of v4.0 has exceeded this limit.We can set android:largeHeap to "true" in the AndroidManifest,so the app could increase the memory limit.
I'm develeping the wallpaper app.The app can show many pictures in high definition.But the memory used by the app always reach the limit of more than 60M in the android of 720p, about 100M in the android of 1080p.
The overuse of memory is unacceptable for me.And I'm looking for the means to resolve it all the time.
My friends,How much memory your app will take up when you develop your app during debugging or running?Is there a memory-manage mechanism in the code?Look forward to your reply.
The amount of memory used by bitmaps is based on what's in the bitmap, not the size of the file. There's a few things you can do to reduce the footprint of the bitmap being loaded in to memory, which, in turn will reduce the amount of memory your app is using.
There's a great talk here from Google I/O for memory management that will help and another that will help you check to see if you have any memory leaks as well.
Also, note that if you use Bitmap.Config.RGB_565 you can half the amount of memory that the Bitmap is using (each pixel value is stored in 2 bytes instead of 4)

Image Conversions in Android?

I want to build an app which converts image formats. I was trying
convert an JPG image to BMP, while doing so i get OOM, cause app
memory is limited that its unable to use the array to store the image
for conversion. If this is the case, how there are apps which does the
same??
I don't know how the actual conversion has to look like, but in every case you will need a buffer or something like that, to consume the jpg. Because Android memory heap is between 24-48mb (one memory block) you run out of memory while trying to convert.
Memory of Android app is limited. The amount of available memory varies by device. So editing big images on an older device might be really a problem.
Solution to this is to use NDK. In NDK you can allocated much more memory than Java apps could have.

OutOfMemory when allocating int array < free memory

In my android app I'm allocating a large int array. This sometimes gives me an OutOfMemory error, when I think there should be sufficient memory. This is an example of what I get:
// always this value
ActivityManager.some_instance.getMemoryClass() = 128 Mb
// always this value
Runtime.getRuntime().maxMemory()/(1024*1024) = 128 Mb
// example value
Runtime.getRuntime().freeMemory()/(1024*1024) = 81 Mb
// example value, can also be bigger than freeMemory()
arrayLengthToAllocate*4/(1024*1024) = 47 Mb
To be clear, I get the OutOfMemory error for situations where the last value is larger or smaller than freeMemory().
Why do I get the error? Is the heap size not increased when the allocation is performed? The memory use of the app just before trying to allocate is about 8 Mb, so that cannot be the problem.
PS. Other approaches than using an int[] of what this app is doing are not possible.
Generally speaking most devices have a cap on the amount of memory you can use. I know that originally this was set at 16MB per application. I think this has increased since, but it is still something you should be taking into account.
You also have to bare in mind that your applications footprint can fluctuate and that the Android Operating System has to give memory to other applications as well which are competing for resources. It may be that Android is identifying your application as being a resource hog and is cutting back it's resources.
Storing 47MB of integers in memory cannot be a very good use of an application's memory, is there no easier approach? I fail to see why you would need so many integers to be so readily available. Surely adding the integers to a SQLite database, reading them in as required, thus moving the bulk of the memory requirements away from RAM and onto physical memory would be a better approach?
When you are hitting OutOfMemory errors it is normally an indication that you are being a bit too greedy and the best way of limiting them is to scale back what you are doing, find a different approach.
The memory amount you get is the system memory size. Each application has a limited subset of that, which depends on a few system variables. In general it's something in the order of 16 - 32 MB, sometimes a bit bigger for tablets.
I figured out that the problem is heap fragmentation. Defragmentation has limits such that there are simply not enough free consecutive bytes in the heap to fit the single large array. I restructered the data into a two-dimensional array which solves the problem as each row has its own location in the heap. Downside is that retrieving the data from the array is slightly slower.

BitmapFactory OOM driving me nuts

I've been doing a lot of searching and I know a lot of other people
are experiencing the same OOM memory problems with BitmapFactory. My
app only shows a total memory available of 4MB using Runtime.getRuntime
().totalMemory(). If the limit is 16MB, then why doesn't the total
memory grow to make room for the bitmap? Instead it throws an error.
I also don't understand that if I have 1.6MB of free memory according
to Runtime.getRuntime().freeMemory() why do I get an error saying "VM
won't let us allocate 614400 bytes"? Seems to me I have plenty
available memory.
My app is complete except for this problem, which goes away when I
reboot the phone so that my app is the only thing running. I'm using
an HTC Hero for device testing (Android 1.5).
At this point I'm thinking the only way around this is to somehow
avoid using BitmapFactory.
Anyone have any ideas on this or an explanation as to why VM won't
allocate 614KB when there's 1.6MB of free memory?
[Note that (as CommonsWare points out below) the whole approach in this answer only applies up to and including 2.3.x (Gingerbread). As of Honeycomb Bitmap data is allocated in the VM heap.]
Bitmap data is not allocated in the VM heap. There is a reference to it in the VM heap (which is small), but the actual data is allocated in the Native heap by the underlying Skia graphics library.
Unfortunately, while the definition of BitmapFactory.decode...() says that it returns null if the image data could not be decoded, the Skia implementation (or rather the JNI glue between the Java code and Skia) logs the message you’re seeing ("VM won't let us allocate xxxx bytes") and then throws an OutOfMemory exception with the misleading message "bitmap size exceeds VM budget".
The issue is not in the VM heap but is rather in the Native heap. The Natïve heap is shared between running applications, so the amount of free space depends on what other applications are running and their bitmap usage. But, given that BitmapFactory will not return, you need a way to figure out if the call is going to succeed before you make it.
There are routines to monitor the size of the Native heap (see the Debug class getNative methods). However, I have found that getNativeHeapFreeSize() and getNativeHeapSize() are not reliable. So in one of my applications that dynamically creates a large number of bitmaps I do the following.
The Native heap size varies by platform. So at startup, we check the maximum allowed VM heap size to determine the maximum allowed Native heap size. [The magic numbers were determined by testing on 2.1 and 2.2, and may be different on other API levels.]
long mMaxVmHeap = Runtime.getRuntime().maxMemory()/1024;
long mMaxNativeHeap = 16*1024;
if (mMaxVmHeap == 16*1024)
mMaxNativeHeap = 16*1024;
else if (mMaxVmHeap == 24*1024)
mMaxNativeHeap = 24*1024;
else
Log.w(TAG, "Unrecognized VM heap size = " + mMaxVmHeap);
Then each time we need to call BitmapFactory we precede the call by a check of the form.
long sizeReqd = bitmapWidth * bitmapHeight * targetBpp / 8;
long allocNativeHeap = Debug.getNativeHeapAllocatedSize();
if ((sizeReqd + allocNativeHeap + heapPad) >= mMaxNativeHeap)
{
// Do not call BitmapFactory…
}
Note that the heapPad is a magic number to allow for the fact that a) the reporting of Native heap size is "soft" and b) we want to leave some space in the Native heap for other applications. We are running with a 3*1024*1024 (ie 3Mbytes) pad currently.
1.6 MB of memory seems like a lot but it could be the case that the memory is so badly fragmented that it can't allocate such big block of memory in one go (still this does sound very strange).
One common cause of OOM while using image resources is when one is decompressing JPG, PNG, GIF images with really high resolutions. You need to bear in mind that all these formats are pretty well compressed and take up very little space but once you load the images to the phone, the memory they're going to use is something like width * height * 4 bytes. Also, when decompression kicks in, a few other auxiliary data structures need to be loaded for the decoding step.
It seems like the issues given in Torid's answer have been resolved in the more recent versions of Android.
However, if you are using an image cache (a specialized one or even just a regular HashMap), it is pretty easy to get this error by creating a memory leak.
In my experience, if you inadvertently hold on to your Bitmap references and create a memory leak, OP's error (an referring to the BitmapFactory and native methods) is the one that will crash your app (up to ICS - 14 and +?)
To avoid this, make your you "let go" of your Bitmaps. This means using SoftReferences in the final tier of your cache, so that Bitmaps can get garbage collected out of it. This should work, but if you are still getting crashes, you can try to explicitly mark certain Bitmaps for collection by using bitmap.recycle(), just remember to never return a bitmap for use in your app if bitmap.isRecycled().
As an aside, LinkedHashMaps are a great tool for easily implementing pretty good cache structures, especially if you combine hard and soft references like in this example (starting line 308)... but using hard references is also how you can get yourself into memory leak situations if you mess up.
Although usually it doesnt make sense to catch an Error because usually they are thrown only by the vm but in this particular case the Error is thrown by the jni glue code thus it is very simple to handle cases where you could not load the image: just catch the OutOfMemoryError.
Although this is a fairly high level answer, the problem for me turned out to be using hardware acceleration on all of my views. Most of my views have custom Bitmap manipulation, which I figured to be the source of the large native heap size, but in fact when disabling hardware acceleration the native heap usage was cut down by a factor of 4.
It seems as though hardware acceleration will do all kinds of caching on your views, creating bitmaps of its own, and since all bitmaps share the native heap, the allocation size can grow pretty dramatically.

Categories

Resources