What does "Out of memory on a ...-byte allocation" mean? (Android) - android

What does these numbers mean below? (caught with LogCat debugger)
08-03 14:29:11.538: I/dalvikvm-heap(6514): Forcing collection of SoftReferences for 14337016-byte allocation
08-03 14:29:11.568: D/dalvikvm(6514): GC_BEFORE_OOM freed 10K, 6% free 115756K/121948K, paused 29ms, total 30ms
08-03 14:29:11.568: E/dalvikvm-heap(6514): Out of memory on a 14337016-byte allocation.
What does 121948K and 115756K mean?
Why 14337016 byte? It is ~14MB. It's impossible! I tried to load a bitmap with 14kB size.

system is trying to free unused memory in order to be able to find some more resources for your application
GC_BEFORE_OOM happens your app's running out of its heap space
more about GC_BEFORE_OOM can be found here
Numbers:
gc freed 10K, 6% is free, which is too little, so it continues deallocation further until gc reaches oom. 115756K/121948K is statistics of the heap of your application
more information about the memory can be found by watching this vid

Related

Android App Memory Usage

I'm in the final stages of implementing a game for the Android platform and have been doing some memory profiling over the past few days. Although the app is running fine within the emulator environment, I am curious to know whether the memory it's using falls within an acceptable range.
While the app has been running, I've captured lines containing details such as the following in the output window:
GC_EXTERNAL_ALLOC freed 14K, 50% free 2939K/5831K, external 2210K/2581K, paused 170ms
GC_EXTERNAL_ALLOC freed 104K, 47% free 3142K/5895K, external 3710K/4633K, paused 263ms
GC_EXTERNAL_ALLOC freed 17K, 48% free 3106K/5895K, external 6362K/6398K, paused 104ms
GC_CONCURRENT freed 98K, 46% free 3225K/5959K, external 7462K/8042K, paused 8ms+8ms
GC_EXTERNAL_ALLOC freed 172K, 47% free 3269K/6087K, external 8023K/8042K, paused 183ms
As you can see, it typically runs with about 48% free memory.
My question is basically whether this is an acceptable amount of free memory?
Thanks,
Wayne.

Defrag/decrease heap size on pre honeycomb

I developed an app that on startup parses some pretty big amounts of JSON which causes the heap to grow close to its limit. A little later the app is loading several bitmaps. On Honeycomb and above devices, which seem to be using the same memory region for bitmap allocations as well as Java object allocations, this isn't causing any issues as the memory needed for JSON parsing has been freed by then. However on pre-Honeycomb devices it causes OutOfMemoryErrors
As the heap size never goes down dalvik seems to not be able to grow the memory reserved for external allocations (e.g. bitmaps).
This is one example log output for a crash
GC_EXTERNAL_ALLOC freed 601K, 81% free 5504K/27591K, external 4809K/5561K, paused 58ms
586224-byte external allocation too large for this process.
As you can see there is plenty of memory available on the heap but not much for external allocation.
Is there a way I can force dalvik to defrag and shrink the heap? Or can I force bitmap allocations to happen on the heap instead of memory reserved for external allocations? Or is there any other approach to this problem I'm missing out on?
** UPDATE **
Here is more log output (the specific device doesn't log dalvik-heap messages):
On startup when the JSON gets parsed the dalvik heap grows:
GC_CONCURRENT freed 800K, 19% free 12717K/15687K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 871K, 19% free 13857K/16903K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 1106K, 19% free 14766K/18055K, external 2637K/2773K, paused 3ms+5ms
GC_CONCURRENT freed 818K, 16% free 15946K/18951K, external 2637K/2773K, paused 3ms+6ms
GC_CONCURRENT freed 825K, 15% free 17151K/20167K, external 2637K/2773K, paused 2ms+6ms
GC_CONCURRENT freed 830K, 15% free 18356K/21383K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 814K, 14% free 19519K/22535K, external 2637K/2773K, paused 2ms+6ms
GC_CONCURRENT freed 823K, 13% free 20720K/23751K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 814K, 13% free 21873K/24903K, external 2637K/2773K, paused 3ms+6ms
GC_CONCURRENT freed 813K, 12% free 23016K/26055K, external 2637K/2773K, paused 2ms+5ms
GC_CONCURRENT freed 1771K, 15% free 23205K/27207K, external 2637K/2773K, paused 2ms+5ms
After that's done most of the heap gets freed again successfully:
GC_EXPLICIT freed 19207K, 83% free 4735K/27207K, external 2736K/2773K, paused 140ms
At this point I have 20 MB free Dalvik heap space and start allocating bitmaps a little later:
GC_EXTERNAL_ALLOC freed 254K, 83% free 4814K/27207K, external 2771K/2773K, paused 47ms
GC_EXTERNAL_ALLOC freed 721K, 83% free 4880K/27207K, external 3881K/4131K, paused 50ms
GC_EXTERNAL_ALLOC freed 235K, 83% free 4870K/27207K, external 5398K/5561K, paused 62ms
Total device limit seems to be 32 MB the dalvik heap takes 27 MB of those and never goes down so I run out of external memory space to alloc bitmaps.
I want to try and tackle this from a completely different perspective. Memory trouble on Android = the damn native heap and bitmaps 90% of the time.. But this doesn't add up here. As far as I recall, the native heap has very little limitations and can grow as much as it wants. The only limitation I recall is a manual test in the dalvik GC that makes sure your used dalvik heap plus your used native heap don't surpass your app heap limit.
What if your troubles are not related to the native heap - only your dalvik heap.
I assumed that your failing 500kb allocation is in the native heap (for the bitmap pixels). There's a chance this allocation is actually in your dalvik heap. Since your heap is so fragmented, the system cannot find a continuous 500kb chunk in your dalvik heap and you crash.
Which bitmap decoding function are you using? Some methods decode directly from a resource to the native heap and some methods (like the ones using a byte array), are decoding from buffers on the dalvik heap which would explain a big allocation there.
To fix this either change your bitmap decoding function and make sure it doesn't allocate on the dalvik heap at all, or better yet, let's fix your entire fragmentation problem at the source.
Here are some ideas to work around fragmentation issues in general (apply these during your JSON handling part in the beginning):
Run System.gc() manually in strategically placed locations. Popular locations are during destruction of large objects like activity onDestroy. Or whenever you finish with a large JSON chunk, throw a manual GC in there.
Assist the System GC free resources faster. This will prevent your heap from becoming fragmented in the first place. Plenty of material on the net on how to do that. Some from the top of my head:
If you have frequent small allocations, try to adopt a memory reuse scheme like making a pool of objects, and reusing objects in the pool instead of allocating new ones. This optimization is often seen in android adapters (like view reuse in listviews)
Manually set variables to null when you don't need them in order to explicitly disconnect them from the reference graph and mark them for easy GC (same goes for explicitly clearing data collections)
Avoid immutable classes when you have plenty of operations, like concatenation of strings, use StringBuilder instead of regular Strings
Avoid finalizers completely
Avoid circular references, or at least change one of them to a weak reference
Use weak references in general where they're needed
You can measure how successful you are by making sure your heap does not grow to huge sizes when you're only using a small part of it
First of all, are you running on the emulator? Because your heap size seems a bit too small. From my calculation you're crashing after about a total of 11MB total use (dalvik+native) and that's very little. Just to verify, do you have a line similar to this after your crash?
08-22 18:16:24.209: I/dalvikvm-heap(471): Clamp target GC heap from 24.610MB to 24.000MB
The max heap size (dalvik+native) is different between devices. The minimum is 16MB and the larger your screen resolution, the larger it is. Devices of 480x800 normally have above 32MB. You can control the heap size in your AVD settings of the emulator, make sure it's big enough to reflect a real device.
Regarding your question, you're not supposed to defray the heap yourself. The VM does that automatically. It is true that the whole native heap mess makes it harder for the GC to estimate problems so you'll get a few OutOfMemoryErrors which you can probably avoid by manually running the GC before large allocations.
More specifically, your large allocations happen when bitmaps are parsed (during calls like BitmapFactory.decodeXXX()). From my experience it actually helps to run System.gc() before them. You only need to do this on pre Honeycomb devices.
Another tip is to free the native allocations as soon as possible. The pixels of your bitmaps are found in the native heap. They are freed only on the bitmaps finalizer, which as you know takes ages to run. This memory will only be freed after several runs of the system GC. This is why it's recommended to free it yourself manually. As soon as you're done with any bitmap, call Bitmap.recycle() to free its native memory immediately.

Wait for concurrent GC blocked

When I run my application on emulator the Logcat is showing this:
04-22 16:21:30.685: D/dalvikvm(967): GC_CONCURRENT freed 1545K, 20% free 7019K/8720K, paused 78ms+17ms, total 360ms
04-22 16:21:30.685: D/dalvikvm(967): WAIT_FOR_CONCURRENT_GC blocked 143ms
04-22 16:21:31.845: D/dalvikvm(967): GC_CONCURRENT freed 1552K, 20% free 7019K/8720K, paused 116ms+18ms, total 554ms
04-22 16:21:31.845: D/dalvikvm(967): WAIT_FOR_CONCURRENT_GC blocked 268ms
04-22 16:21:32.435: D/dalvikvm(967): GC_CONCURRENT freed 1545K, 20% free 7019K/8720K, paused 75ms+9ms, total 192ms
04-22 16:21:32.435: D/dalvikvm(967): WAIT_FOR_CONCURRENT_GC blocked 73ms
04-22 16:21:32.945: D/dalvikvm(967): GC_CONCURRENT freed 1552K, 20% free 7019K/8720K, paused 75ms+10ms, total 209ms
04-22 16:21:32.945: D/dalvikvm(967): WAIT_FOR_CONCURRENT_GC blocked 70ms
04-22 16:21:33.434: D/dalvikvm(967): GC_CONCURRENT freed 1545K, 20% free 7019K/8720K, paused 78ms+12ms, total 192ms
and this continues until I exit the application.Any suggestion?Thanks
Seems like you're creating many new objects and throw them away soon.
For WAIT_FOR_CONCURRENT_GC see this one:
what does WAIT_FOR_CONCURRENT_GC blocked mean?
It means you try to allocate memory (for example object creation) and it doesn't fit into memory. Thats what GC_CONCURRENT freed is caused by. Its just usual garbage collection.
If you've got performance problems, try to reuse objects or spare them.
This means you are doing too many operations and a lot of memory is being used. Hence, GC(Garbage collector) is being called to free up memory.
04-22 16:21:30.685: D/dalvikvm(967): GC_CONCURRENT freed 1545K, 20%
free 7019K/8720K, paused 78ms+17ms, total 360ms
freed indicates how much memory was freed
GC_CONCURRENT Invoked when the heap gets too large to prevent overflow.
paused 78ms+17ms – indicates how much time it took the GC to finish collection.
Refer
Additionally take memory dump and analyze the dump use MAT tool.
Agree mostly with #luxer, but I believe it's not that you are allocating too many objects, but you are allocating some huge objects. If you refer to the link pointed by #luxer about WAIT_FOR_CONCURRENT_GC, you will realize that a second gc is being triggered in your app while a concurrent gc (which is typically triggered when the heap occupancy hits a soft limit) is in progress. The second gc could have been triggered by you explicitly or because an allocation failed. Since you have not indicated that you're calling System.gc(), I would assume that your allocations are failing and the system is trying to do a gc.
So, yeah, you should seriously consider reusing some huge objects instead of allocating them each time. This is a better practice, but if for some reason you're unable to do that, you can probably bump your heap size (by setting large heap) and that may help.
Sometimes it happens when you have a never ending loop just because some condition is always true.
Try to figure out if its this case first as it happens mostly because of this.
I was able to resolve mine by debugging my code : There was a DB operation lurking in an infinite while loop, which was filling the bean and hence causing the memory leak.
Maybe if you'r a a newbie like me, please check on the while/do-while/for loops and object allocations done in loops.
Un closed connections and Cursors should also be closed.
Thanks,

Garbage collection in dalvik vm

I connect my android phone to eclipse. And I see these message from Logcat.
Can you please tell me what does is the difference between 'GC_EXPLICIT' and 'GC_EXTERNAL_ALLOC'? and what does "45% free" mean?
10-05 12:08:34.450: DEBUG/dalvikvm(813): GC_EXTERNAL_ALLOC freed 63K, 45% free 3156K/5703K, external 4113K/4348K, paused 73ms
10-05 12:08:34.480: DEBUG/dalvikvm(101): GC_EXTERNAL_ALLOC freed 55K, 40% free 5883K/9799K, external 4911K/4913K, paused 124ms
10-05 12:08:37.120: DEBUG/dalvikvm(101): GC_EXPLICIT freed 84K, 41% free 5870K/9799K, external 5745K/6078K, paused 104ms
10-05 12:08:40.099: DEBUG/dalvikvm(493): GC_EXPLICIT freed 14K, 48% free 3782K/7175K, external 1625K/2137K, paused 75ms
10-05 12:08:45.110: DEBUG/dalvikvm(188): GC_EXPLICIT freed 57K, 54% free 3203K/6855K, external 4988K/6206K, paused 78ms
10-05 12:09:05.119: DEBUG/dalvikvm(822): GC_EXPLICIT freed 349K, 46% free 3696K/6727K, external 1625K/2137K, paused 65ms
I would highly suggest giving the Memory Management video presentation from Google I/O 2011 a watch:
http://www.youtube.com/watch?v=_CruQY55HOk
At about 14 minutes in, he goes in to depth on exactly what these mean in the logcat output.
GC Explicit basically means that an app has explicitly called System.gc();
GC Concurrent is triggered when your heap starts to fill up and a Concurrent GC kicks in to hopefully clear memory before it fills up.
GC_EXPLICIT means your app has explicitly called System.gc() or the Activity Manger of Android System called System.gc()
GC_EXTERNAL_ALLOC is something more complicated.
There are some memory related to the life time of Java's object called EXTERNAL memory. Such as memory use by GPU or pixmap resources of your app. This type of memory allocating use "malloc" of stdlib to allocation heap memory but NOT allocating from the GC Heap of Dalvik, but it's also one of the "HEAP" memory. And the total size use of the HEAP must be smaller than a limit(decide by GC).
Dalvik tracking allocation of that memory.
CONDITION: usableof(GC_HEAP) + usableof(NATIVE_HEAP[external]) <= allocaionLimit
Dalvik will cause a GC for GC_EXTERNAL_ALLOC as a sideeffect when the condition above is not true.

What are the "paused" values in GC_CONCURRENT log messages?

I'm trying to explore the behavior of the new concurrent garbage collector in GingerBread (2.3).
Could someone please explain these example log lines in details (especially the "paused" parts of GC_CONCURRENT and GC_FOR_MALLOC)?
12-24 10:20:54.912 D/dalvikvm( 414): GC_CONCURRENT freed 510K, 57% free 2529K/5831K, external 716K/1038K, paused 8ms+5ms
12-24 10:20:54.963 D/dalvikvm( 414): GC_FOR_MALLOC freed 510K, 57% free 2529K/5831K, external 716K/1038K, paused 47ms
GC_CONCURRENT Heap is (almost) full. Therefore concurrent GC kicks in
freed 510K - Amount of memory freed
57% free - Memory after freeing %
2529K/5831K - Actual mem in heap
external 716K/1038K - Externally allocated memory (memory that is not in dvm)
paused 8ms+5ms - time taken for GC
especially the "paused" parts
For concurrent collections there are two pause times. One is at the beginning of the collection and other towards the end. For non-concurrent collection there will be only one pause time.
if you haven't yet, check out this video:
http://www.google.com/events/io/2011/sessions/memory-management-for-android-apps.html

Categories

Resources