Memory issues loading images for app - android

Describing background, as I may just have a terrible approach to the problem - self learning.
I'm writing an app for android, and testing it on default AVD, which is set to WVGA800 with 512 'device ram size' and 240 'Abstracted LCD density'.
I have some images, and I put them into drawable-hdpi.
There are 458 KB (not MB) worth of images in that folder.
All images are in PNG format.
The issue is that when I try to load my biggest image (used for background), it throws: java.lang.OutOfMemoryError
This is the call to load the image:
BitmapFactory.decodeResource(status.getResources(), R.drawable.background);
This is identical to how I load the rest of images (33 in total).
It makes sense to me, that it would run out of memory on biggest image, but my total size of folder is 458 KB, so I wouldn't expect to run out of 512 MB Ram set on device.
I never unload any images, I keep them loaded, and use as needed.
I wrote a different app before, where my total size of images was 563 KB with 82 images total, and I didn't have this issue (using the same AVD). In fact the prior app used to make a couple of copies of each image by flipping it, and still didn't run out of space. Current app is failing on initial load - before much happened.
Could someone point me at what the issue could possibly be? And how I can solve it, or maybe mention if my approach is wrong (self-teaching myself from examples)

I'll give you some hints on how i manage to lessen that problem
If you plan to support all devices, put all your resource into the xhdpi folder. especially the background
File size != memory size

Keep in mind a few things:
Your application has a memory limit (this depends on the android version). You don't get all the device memory. I think that first android version have a memory limit of 16mb.
The size of the file doesn't represent the size of the bitmap in memory. For example a 32bit ARGB bitmap will take 32*width*height bits
If you are dealing with big images then scale them first. Calculate the size you need (this will probably be the size of your ImageView) and load a resized copy of the bitmap. You can do this using BitmapFactory.Options

Yea, this is a pretty common problem. So in older versions of android OS, the bitmap was loaded into native memory and not the JVM. The garbage collection process would really have 2 cycles. One to clear out the memory in the JVM and the other to clear out the memory in the native memory (for bitmaps). If you want to work on older devices, you will need to handle this situation by either recycling your bitmaps Bitmap.recycle() or calling System.gc()
There are two problems that you might be hitting:
1. You have other bitmaps that are un recycled.
2. You really are running out of memory because that single image is too big. (Make sure the other images are correctly recycled or gc'd so that it doesn't add to the memory footprint). In this case, no much you can do.
ALso, as mehmet suggested, you can read this

Related

Huge byte[] in my app after HPROF

From time to time, especially when implementing new functionalities in my app, I use DDMS + HPROF to analyze memory and heap use. As the App doesn't seem to have any performance-ANR issues and everything works smoothly, initially I didn't care about it - but now, as I see it's approximately always the same size, I'm wondering what the damn can it be.
Everytime I run a HPROF, I check the Leak suspects tab. There's always an android.graphics.Bitmap instance that takes approximately 25% of all the used heap.
I wanted to know a bit further what's that about, so I opened the dominator tree, and saw this:
So esentially there's a huge byte[] instance that is retaining a lot of heap, and never gets released. According to this, I copied the value of that byte[], dumped it into a .data file, opened with Gimp, and there's the result:
So basically, it looks like the "alpha(0)" part of a PNG image. Having in consideration the following facts:
All my image files are <8K in size
Just some of them are PNG - the remaining I was able to convert to JPG, I did
No matters if I add further images, the size of that byte[] has been always aproximately the same from the beggining of the app (4 months ago)
To debug it, I tried to remove any image file from the drawable and drawable-xxx folders and run the app without any drawable resources, and the byte[] was still there
I removed almost all layouts and let just the basic funcionality, and same result
In the Dominator tree, the root class is android.graphics.Bitmap
Anyone knows what it this byte[] and if I should do anything to free it up?
Any help appreciated!
Just to clarify a few things:
Images/drawables in your app are used in memory in the form of android.graphics.Bitmap.
As of Android 3.0 (API level 11), the pixel data is stored on the Dalvik heap along with the associated bitmap. (Managing Bitmap Memory)
"huge byte[]" is probably an overstatement as it is just over 1MB of heap space.
The Leak Suspects report can be helpful, but in this case it isn't telling you much considering that its largest suspect is just over 1MB of memory. Modern devices are offering 64MB+ heaps.
Let's do the math for the memory requirements for this bitmap. This bitmap is taking up 1,127,584 bytes on the heap. If we were to assume this bitmap is configured using ARGB_8888, each pixel is using 4 bytes, which means your image contains 281,896 pixels (or roughly 530x530). Does this sound unreasonable for what you are doing?
Also, consider the way Android scales across the different "buckets" for drawables: mdpi, hdpi, xhdpi, etc. Let's say you have a 200x200 image in the mdpi bucket and you are opening the app on a xhdpi device. This image will be scaled to be twice as large and will have a on-device resolution of 400x400. So while the 200x200 image may not take much heap space (200 x 200 x 4 = 160 kb), the 400x400 image will require a relatively larger amount (4x) of heap space (400 x 400 x 4 = 640 kb). For more information on this, see Supporting Multiple Screens.
A nice tool for quickly computing differences with the image buckets: Android DPI Calculator
You said you removed some of your drawables, but what is left? Have you considered drawables that may be coming from external libraries?
To answer your final question: Anyone knows what it this byte[] and if I should do anything to free it up?
I would say: This small amount of memory on your heap is nothing to be worried about. If it is bothering you, keep an eye on it and make sure it isn't growing beyond what seems practical. If you still suspect a memory leak, navigate between screens and watch to see if the heap continues to grow. Assuming you are not caching bitmaps, the heap should maintain a consistent/predictable size when navigating back and forth between two screens
As a side note, DDMS makes it very easy to monitor heap size on the fly. No need for HPROF dumps until you are ready to dive in. Have a look at Using DDMS. Take special note of the "Cause GC" button as it will be needed to trigger the update of the initial heap size.
-- UPDATE --
To further answer this, one unsupported suspicion I have is that some of the app's assets (system assets/textures?) are loaded into your app's memory space. Have a look at slide 64 here: What's new in Android 4.4.
Android 4.4 now generates a single texture containing all the framework assets, shared by all processes. This saves a bit of memory in every process but it also helps batching and merging drawing operations to optimize applications automatically.
This seems to imply that memory is used for system bitmaps/drawables in each app running a version prior to 4.4. If this is the case, I would question if this 1MB is that space. I wonder if you could run your app on a 4.4 device/emulator and see if the same memory is used.
As another test, have you tried inspecting memory usage on a barebones app (all drawables removed, etc)?

Android memory management: Screen density, requested image sizes and available heap

Guess what, another Android-Bitmap-OOM question!
Background
Whilst stress testing our application it has been noted that it is possible to max-out the app's process memory allocation after sustained, heavy usage (monkey runner like) with OutOfMemory exceptions being recorded within the ensuing stacktrace. The app downloads images (around 3 at a time) when a page under a ViewPager is selected. There can be 280+ images available for download when the length and breath of the app is exercised. The application uses Picasso by Square for it's image downloading abstraction. Notably, at no point in our application's code are we manipulating Bitmaps directly...we trust that the very talented Square Inc. employees are doing it better than we can.
Here is a picture
The below plot shows the heap allocations over time recorded under the dalvikvm-heap log message. The red dots indicates a user bringing a fresh set of articles into the application in order to bolster the amount of work outstanding and stress the app...
DALVIKVM heap allocations http://snag.gy/FgsiN.jpg
Figure 1: Nexus One heap allocations; OOMs occur at 80MB+
Investigation to-date
Against a Nexus S, Nexus 4, Wildfire, HTC Incredible and a myriad of further test devices, anecdotal testing has shown the memory management to be sufficient with the DVM GC 'keeping up' with the heavy lifting work being completed by the app. However, on high end devices such as the Galaxy S II, III, IV and HTC One the OOM are prevalent. In fact given enough work to do, I would imagine all of our devices would eventually exhibit the failure.
The question
There is clearly a relationship between screen density (our requested image sizes are based off the size of the ImageView), the process memory allocation and the number of images at a given size that would result in the app exceeding it's heap limits. I am about to embark on quantifying this relationship but would like the SO community to cast their eyes over this problem and (a) agree or disagree that the relationship is worth making and (b) provide literature indicating how best to draw up this relationship.
It is important to note that if we destroy the image quality our OOM all disappear but alas the UX is poorer which is why we are wanting to be dicing with the most effective use of the available heap.
Side note: Here is the portion of code responsible for loading these images into the views that have been laid out;
picassoInstance.load(entry.getKey())
.resize(imageView.getMeasuredWidth(),
imageView.getMeasuredHeight())
.centerCrop()
.into(imageView);
The 'dashing of image quality' mentioned above is simply dividing the imageView.getMeasured... by a number like '4'.
First you need to manage the memories allocation ,its a big issue in android as bitmaps takes lots of memories ,for that memory allocation can be reduce by following ways
put all those images which are huge in size to assets folder instead of putting them in drawabable folder . because drawable resources takes memory for caching them .if you load from asset folder the image will not cache .and will takes less memory .
study Lrucache which use for efficient memory management .
put resources in tiny formats for that check TinyPNG
if your images are too large in resolution , then try to use SVG files for images and load SVG file instead of image . check this SVG FOR ANDROID
finally i am not very good in English hope it may helps you.
This post is a little old but I also had this issue recently. Maybe this will help someone else.
General Overview of this massive thread/What helped me.
-Make sure you are using a Singleton Instance of Picasso
-Use fit()
-For large Images or many Images or when used in a FragmentPager/StatePager you should probably use skipmemorycache() and/or largeHeap declaration
Read the thread for more tips. At the time this question was posted nobody had posted this issue on picassos github.
https://github.com/square/picasso/issues/305

Android java.lang.Outofmemorry+imports

I would like ask you simple question.
I fight with java.lang.outofmemory error. I
t is caused probably by pictures but also I have in my project quite alot unused imports and unused variables at this moment (application with 7 activities and every activity aprox 40 variables).
Take unused imports and unused declared variables memory ?
Do you think, can be java.lang.outofmemory error caused of many variables and imports ?
From Android:
Bitmaps take up a lot of memory, especially for rich images like
photographs. For example, the camera on the Galaxy Nexus takes photos
up to 2592x1936 pixels (5 megapixels). If the bitmap configuration
used is ARGB_8888 (the default from the Android 2.3 onward) then
loading this image into memory takes about 19MB of memory (2592*1936*4
bytes), immediately exhausting the per-app limit on some devices.
Basically, Images are a killer if not used properly.
See this android tutorial on Loading Large Bitmaps Efficiently
Specifically, the code examples to loading in scaled bitmaps from files/resources, at the required resolution.
Imports have no effect on the memory, at run time. The only thing they might do is slow down the build time. Nothing detrimental.
No, variables not occupy more memory in Heap of application. This may be due to bitmap in your application. If you are getting any error, make sure you have released images background like
imageview.setBackgroundDrawable(null);
relativeLayout.setBackgroundDrawable(null);
or
imageview.setBitmapImage(null);
This will remove drawable images used in layouts.

Android VM heap strategies for big images

I am manipulating relative large images, about 5MP and sometimes even more. I need two copies of the images in memory for manipulation.
Now, the loaded images consume a lot of memory, more than available by the default Android heap which is 16MB respectively 24MB which results in the following error:
11-20 18:02:28.984: E/AndroidRuntime(7334):
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
I need full resolution, thus downscaling while loading the images does not help.
What's the best solution to get over this problem? Are there built-in methods to dynamically load only chunks of bitmaps from storage? And can someone give me some hints how I can overcome the memory problem, e.g. by using specific caching strategies?
Regards,
You can allocate more memory in the ndk. You'd have to write native code to manipulate the images, or you'd have to figure out a way to allocate the image memory in native, then pass it back to Java.
Bitmap/Canvas use and the NDK
Another option might be to load a single image into memory, and break it up into chunks for processing. Save those chunks out to the file system. So, say you 2 large images. You load the first image, break it into 4 parts, save them, load the second, break it into 4 parts, save those, then load part #1 for each image, and do your thing. That implies you know that neither individual image is larger than the heap max, and that what you need to do is (basically) pixel level and doesn't need access to surrounding pixel data (you'll run into trouble at the edges if you need neighbor pixel info).
Without downsampling, splitting, or ndk, I don't know how you'd get more image data into memory. Perhaps lowering the color info. We do this in a product. Represent each pixel as 16 bits rather than 24 or 32. Our product is functional rather than "pretty", so the loss of color info wasn't a big deal.
You should watch this video on memory management: http://www.youtube.com/watch?v=_CruQY55HOk
At about 6 mins into it he covers the LargeHeap manifest option added to HoneyComb.

android memory management outside heap

I am working on an application for android and we since we have lots of graphics, we use a lot of memory.
I monitor the memory heap size and its about 3-4 Mb , and peeks of 5Mb when I do something that requires more memory (and then goes back to 3). This is not a big deal, but some other stuff is handled outside the heap memory, like loading of drawables.
For example if I run the ddms tool outside eclipse, and go to sysinfo, I see that my app is taking 20Mb on the Droid and 12 on the G1, but heap size are the same in both, because data is the same but images are different.
So the questions are:
How do I know what is taking the memory outside the heap memory?
What other stuff takes memory outside the heap memory? Complex layouts (big tree) ? Animations?
Thanks
Daniel
Bitmap objects takes a quite alot of memory.
Ex. if your app downloads a 10KB jpg from net and use BitmapFactory to decode it into a Bitmap that bitmap objects needs about 30-100KB memory, depending on the resolution of your image. 3bytes for each pixel (1 byte for each color)
And yes, all kind of object uses memory, like LinearLayouts, ImageViews etc... If you are creating and destroying many of these objects, ex. as you scroll / page through your images, there will be memory leaks. The gc() does not handle so-called short lived objects as fast as we would like.
*Keep the number of view objects at a stable level**, and recycle them instead of destroying and creating new ones.
REf: http://developer.android.com/resources/articles/track-mem.html
If your app reaches 20MB in memory, it may FC as the BitmapFactory is trying to decode the next image.
One obvious candidate is off course off-screen bitmaps (double-buffering by android?), since the screensize has ~4x as many pixels on the droid.

Categories

Resources