How to view bitmaps taken from memory dumps? - android

Background
android apps usually have a low amount of heap memory for them. that's why you always need to avoid holding large objects.
since the app i'm working on can get OOM on some cases, i thought that i should check out what causes the memory to be low.
i've used MAT plugin and i've found out that the app has 3 bitmaps that take 3.5MB each.
The problem
the app already has multiple bitmaps being used, but they are way smaller (less than 1MB each).
in fact i've even put breakpoints to make sure each bitmap i create don't take so much memory, and found nothing.
i've also watched some google IO videos (like this one) regarding this matter. it seems that in order to see which class has a reference to the object, you click on the object and choose "Path to GC roots"=>"exclude weak references".
What I've tried
you can see in the dominator-tree which bitmaps take the most (look at "retained heap").
in order to export the data, you can choose the byte array and then "copy"=>"save value to file".
however, like others have tried on this post , i'm stuck at showing the bitmap itself (need to know its format, width and height). plus it could be quite annoying to use GIMP for this task.
The question
how can i view the bitmaps (the image itself) within eclipse?

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.

Determining available memory for bitmaps

I'm working on a graphical app for which I want to keep an array of bitmaps that are used for Undo operations. The bitmaps are quite large at around 9M each, so I realise I can only keep a few in memory at any given time.
I'd like some way of working out in advance how many I can have.
I've tried various ways of querying available memory, and am being careful to recycle bitmaps once they are not needed, but despite that the app seems to crash with EOutOfMemory.
I don't want to scale down the bitmap, or use RGB565. I just want a reasonably reliable way to figure out how many undo steps I can allow for.
Thanks
EDIT #1
I've continued to try various ways of determining available memory, including those linked to in the comments, but still am having problems.
The strange thing is that my old Samsung I9000 phone doesn't have too many problems creating and accessing lots of bitmaps each 9MB in size, but my newer Samsung Tab 3 dies allocating the 3rd one.
It should have plenty of memory available. I did read something about there being differences in where memory is allocated for bitmaps on Android 3 and above, but don't fully understand it. Could this be what is causing my Tab to die with EOutOfMemory?
EDIT #2
In desperation I decided to turn on largeHeap in the manifest. I know it's not recommended, but it has made the Tab 3 behave more predictably, and it possibly demonstrates something about the underlying problem.
This reminds me of a very common mistake , of putting the image files into the "res/drawable" folder.
Such a thing causes the bitmaps to take much more memory the higher the screen density is.
for example, for a 100x100 image, it would take only 100*100*4 = 40,000 bytes on an mdpi device, but it will take (2*100)*(2*100)*4 = 160,000 bytes on an xhdpi device (4 times more).
however, since the galaxy tab 3 doesn't seem to have a high density screen, i think that you get OOM because the heap size is small for holding all the bitmaps.
check out my post here for some memory and bitmaps tips.
It seems that getting available memory is a bit quirky in Android, but it turned out that my main problem was that on newer versions of Android the memory allocation for bitmaps has changed, and they now easily blow the limit of the heap.
Setting largeHeap in the manifest got me around that problem, but I'm still not sure it's ideal.

android:largeHeap="true" convention?

I'm writing an image gallery app and I keep running into out of memory errors. I cache all my images but the problem occurs when I try switching between images really fast. I'm assuming the app is allocating memory faster than the GC has time to free them up (because the crash doesn't happen when I switch images slowly).
After banging my head against this problem for days, I finally decided to give largeHeap setting in the manifest file a try. After this setting, my app no longer crashes no matter how fast I switch between images.
Now, I want to know if there is any convention or general guideline to using largeHeap setting because it probably wouldn't make much sense if, say, a note taking app used largeHeap. Generally speaking, what apps are a good candidate for largeHeap setting?
Thanks
Generally speaking, what apps are a good candidate for largeHeap setting?
Ones where you can justify to the user why you're forcing all their other apps out of memory, to give you an outsized amount of heap space.
Personally, I would not consider "an image gallery app" to qualify. AutoCAD, video editors, and the like would qualify.
With respect to your memory management issues, make sure that you are using inBitmap on BitmapOptions when running on API Level 11+, so you recycle existing buffers rather than go through garbage collection. Particularly for an image gallery, where you probably have a lot of fairly consistent thumbnail sizes, recycling existing buffers will be a huge benefit. This can help both overall memory consumption (i.e., you are truly out of memory) and memory fragmentation (i.e., you get an OutOfMemoryError with plenty of heap space, but no single block big enough for your allocation, due to Android's frakkin' non-compacting garbage collector).
You might also consider looking at existing image cache implementations, such as the one that Picasso has, to see if there are some tips you could learn (or possibly just reuse).
First, make sure you aren't loading larger bitmaps than necessary:
Load a Scaled Down Version into Memory.
Then, before trying largeHeap, try to free the memory quickly yourself:
If you call bitmap.recycle(); as soon as you are SURE you will not use a bitmap again, then the bulk of that bitmap's memory will be immediately freed. (When the GC gets around to it, all that remains is a tiny object.)
On newer Android versions, there are alternatives (instead of recycle) that may be more effective:
Managing Bitmap Memory
Personally, I still use recycle often, especially if I might be loading a different size image, so can't reuse the existing one. Also, I find it easier to code "unloading" of old media separately from "loading" of new media, when changing to a different fragment or activity:
As leave the old fragment, all old bitmaps I recycle (then, if reachable from a static field, set to null).
The rule of thumb for whether to use largeHeap, is to consider it after you've tried alternative ways to reduce memory usage.
Code your app so you could turn it off again, and still run.
For example, monitor your memory usage, and load "scaled down" bitmaps if memory is tight. Will the user really notice if a given image is not at their device's "retina" resolution?
Or if it is an older, slower, device, will largeHeap make your app feel unresponsive / jerky? If so, can you drop resolution even further, or show fewer bitmaps at one time?
Get your app to work in all circumstances, without largeHeap [by techniques mentioned above]. NOTE: you can "force-test" running on tight memory, by allocating some "dummy" bitmaps, and hold references to them in global fields, so they don't get freed.
NOW you are able to evaluate the trade-off, as it affects YOUR app:
When you do turn largeHeap on, use your app heavily - are there places where it is now "more sluggish", or animations "stutter" or otherwise seem less smooth? BE SURE TO TEST ON AT LEAST ONE OLDER DEVICE, AND ON ONE HIGH_RESOLUTION DEVICE.
You might be seeing long GC times, due to the larger heap.
OR you might conclude that largeHeap is working well for you, and now you can confidently say that it is the best choice in your circumstance.

Is there a way to compact memory in android to lower the high water mark?

Please note I do NOT have a memory leak. My question is about a subtler issue.
I recently wrote an android app which does image processing. The image is loaded as a Bitmap, then copied out in pixels, processed in a way that uses lots of memory (think Fourier transforms in floating point representations and stuff), then converted back into a bitmap and saved.
The problem is, through at least android OS 2.3, the total memory limitation (typically 16MB) is combined java and (externally stored) Bitmaps, and the java high water mark doesn't go down (that I can discern) even when the memory is free (successfully GC'd), which means when I go to allocate the final Bitmap, I am often "out of memory" even though by that point I have freed (and GC'd) most of the space. I.e., I never need the full 16MB at once, but the space left for Bitmaps appears to be 16MB minus the MAX historical java heap usage (as opposed to current usage).
I watched a tech talk by one of the android developers about memory issues and he implied this problem has been fixed in subsequent versions of the OS (they moved Bitmap memory into the java heap space), but in the meantime most of the people wanting to use my app are running 2.2 or 2.3.
Long story short, I am wondering if the java heap is ever compacted (de-fragmented, in effect) so that the high-water mark shrinks (and if so, how to make it happen)?
If not, then does anybody have another suggestion how to deal with this problem?
Long story short, I am wondering if the java heap is ever compacted (de-fragmented, in effect) so that the high-water mark shrinks (and if so, how to make it happen)?
Whatever its behavior is, it most certainly is not under your control.
If not, then does anybody have another suggestion how to deal with this problem?
Ideally, reuse your own Bitmaps. You don't indicate what "processed in a way that uses lots of memory" really is. However, if it does not change the dimensions or bit depth of the image, copy the data back out to the original Bitmap rather than allocating a fresh one, if you can.
Image processing on Android 2.x is one of the few places where I can see justifying using multiple processes. You will add overhead for schlepping the image data between processes, but the other process has its own heap (Java and native), so this may give you more "elbow room".
So far, no indication that there is any way to compact the memory.
Here is my workaround, which is suboptimal but much better than the behavior before:
I now intentionally hold on to the original Bitmap while I am doing my processing, and then recycle() and null it, and GC(), but not until just before allocating my output Bitmap.
What this does is reserve external (Bitmap) space, and cause my application to run out of java heap (during processing, before calling recycle()), which I can at least catch and handle by retrying on a smaller image. (Before, everything seemed to be fine until I tried to save, but by then it was too late and with no way to recover.)
Technically this limits my max image size to less than I should be able to do with the allotted memory (because I need to reserve space in the heap and external at the same time when in truth I never need both together), but at least I can still handle a reasonable image size.
What was happening before is I would free and recycle the Bitmap early which allowed the high water mark on the java heap to use up essentially all of my memory allotment, meaning from that point forward I couldn't open or create any more Bitmaps at all (other than tiny thumbnail sizes sometimes).
Imo, this is a major bug in the way android handles Bitmap memory, but I believe it is fixed in newer versions of the OS so hopefully I can disable this workaround conditional on the OS release.
I'm assuming that you already call Bitmap.recycle() but it's the only thing I remembered and you didn't talk about.

Categories

Resources