How Are Bitmaps Stored in Memory in Android? - android

Haven't been able to find this one out.
How are Bitmaps stored in memory in Android? More specifically what I'm looking for is, does it store the information pixel by pixel, or does it use any sort of algorithm to reduce the number of stored pixels, like storing a single pixel and a number for how many times to repeat it in a row. I'm wondering about this because we're having trouble fitting all the images we want into our game. If it does use some sort of algorithm, then we can do something to the original image to cut down on memory consumption, right?

Bitmaps are stored compressed, but you pretty much can't display one without assembling the pixels at some point. Your best bet is probably to save your limited CPU heap and push your images into the GPU as compressed OpenGL ES textures.
Additional:
Have a look at Displaying Bitmaps Efficiently. Also recycle your bitmaps if it helps.

While an implementation may choose to use RLE to store bitmaps in memory, I very much doubt one would do so since it would be inefficient to operate with them.
On Android 3.0 and above, you can request a larger heap.

Related

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

Tracking down android memory usage with MAT

I'm trying to work out where some of the memory usage of my app is coming from using MAT.
There's some references that to bitmaps which seem to retain a lot of heap. Is there any way to determine what actual resource they are? The images generally coming from drawables within the app. There's object references, but I can't work out how to drill down to determine which actual drawable may be taking up the memory.
E.g. there's a Bitmap with a retained heap of over 1mb and lots over 300k
Define your real problem. Bitmaps of these size are quite normal: between 200x200px and 500x500px or so.
If you have OutOfMemoryErrors, when first approaching app I like to use histogram (second icon, with 3 blue bars) and filter on your.package.*Activity. If there are too many instances, that possibly means there is a memory leak.

How much hashMap operation can be called 'safe' at a time

I am developing an application in which I have a database with 5000 rows with 4 columns.
problem_id (int)
problem_no (string)
problem_title (string)
dacu (int)
I need to frequently query single items in a large scale like 1000 query to fetch problem_no based on problem_id or sometimes only one item.
So I decided to query all the database rows and map them in a hashMap at runtime. I know hashmap insertion/query operation will take only O(1) or sometimes little more, so I only need 5000 operations I think. But how much space hashMap will take in this case? Would android dalvik be able to allocate them without any trouble?
How much space will hashmap take?
It's an implementation detail that can vary between versions, devices, etc. As long as we understand that and look for an estimation only, you can actually measure it very easily. Android SDK includes a powerful suite of memory analysis tools. Check out Eclipse MAT (the best one in my eyes). You can take a heap snapshot when your hashmap is fully loaded, then use MAT to see how many bytes it takes. Make sure you sum up both the hash itself, the keys and the values (if I remember correctly MAT can do the math for you too (it can handle the core collections very well).
Will dalvik be able to allocate?
For the sake of discussion let's say your hashmap takes 1MB of memory. To get a feeling if that's much, we need to understand the constraints of the system we live in. Dalvik limits the max size of your heap. The limitation varies per device. The minimum on very old devices is 16MB. Devices like Samsung Galaxy 2 have about 32MB-48MB and new devices like Galaxy 3 and 4 have more than 100MB.
The biggest memory hog in apps is usually bitmaps. Since every pixel can take as much as 4 bytes, a full screen bitmap can easily eat up a few MB of memory.
With this in mind, a toll of 1MB doesn't sound bad. It's comparable to a using a nice background image :) if your overall memory usage is low, you can distribute it as you see fit. The memory analysis tools (MAT or DDMS) let you know exactly how much memory your app is currently using, so you can easily estimate how much your total consumption will be.
Other thoughts:
Caching things in memory to improve performance is usually a good idea. So your approach is a good one in my eyes (as long as you understand the memory implications).
Since your memory hashmap is an optimization only, you can be extra careful and only do it when you have memory to spare. You can easily measure the amount of available heap (the is API for that) and make your decision accordingly. You can listen to low memory notification events (google about those). And you can even catch OutOfMemoryError exceptions of failed allocations and change your memory strategy in runtime.
You are playing in a field where exact measurements are difficult. Be sure to QA on several devices and several versions of Android. To simulate low memory settings, try to use the oldest devices you can find.
I personally think that you will have absolutely no issues handling what you want in memory. Especially if those things are just primitives (no bitmaps).
I have used queries for up to 10k rows for caching in memory and had absolutely no issues in terms of memory for them.
The issue might happen when you need to process everything. Like how fast is it to get to a specific item, get all realated items etc..
One issue i have come accross was UI related. I tried to just fill an adapter and show it in a list with all 10k of rows which took about 7 seconds to complete. It was long time ago and i don't recall why exactly that happened, but what i am saying is that i would pay more attention to keep processing outside of the UI thread and manage that as much as possible rather than memory in your case.

Why does Android allocate more memory than needed when loading images

Folks, I don't think that this is a duplicate and is NOT one of those how do I avoid OOMs questions. This is a genuine quest for knowledge so hold off on those down votes please...
Imagine I have a JPEG of 500x500 pixels. I load it as ARGB_8888 which is as "bad as it gets".
I would expect Android to allocate 500x500x4 bytes = a little under 1MB however, look at a heap dump and you will see that Android allocates significantly more, often factors of 5-10 times greater.
You frequently see questions on here about OOMS where the stack trace shows a heap request of say 15MB and it is Always much larger than is required simply to hold the bytes of the image. The OP usually catches some downvotes then is bombarded with stock answers and comments about using less memory (thanks Romain!) and in scaling. I think there is more than meets the eye here.
Anybody know why this is?
If there is no apparent answer, I will put together an SSCCE if it helps.
PS. I assume that JPEG vs PNG etc is irrelevant since we're talking about the memory usage of the backing bitmap which is simply x times y times BPP - or am I being slow?
It used to be quite a common trick with memory management to grab a pool or block of memory which is parceled out into smaller requests. When I worked with embedded systems it was a common practice to maintain pools of memory of different sizes, and we just allocated a block larger than the amount requested from a pool . It is a convenient way of preventing too much memory fragmentation. Maybe this is happening here.

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.

Categories

Resources