Follow is part of dumpsys meminfo's outputs:
We can see:
Native heap size is 65 MB
heap alloc is 22MB, while free is about 3MB
but alloc + free is quite smaller then size.
Why?
Related
I would like to check how much free memory available in android device. so I run free command:
total used free shared buffers
Mem: 3.5G 3.5G 34M 9.4M 25M
-/+ buffers/cache: 3.5G 59M
Swap: 2.0G 66M 1.9G
This result looks like weird, Is the free memory 34M + 59M + 1.9G = 2.8G?
Fatal Exception: java.lang.OutOfMemoryError
Failed to allocate a 165377344 byte allocation with 8507672 free bytes and 8308KB until OOM, target footprint 536870912, growth limit 536870912
I am creating an app that processes very large images on the jni side. And by very large images I mean that nearly all of the devices available RAM gets allocated into a few large blocks. The problem is that after allocating and releasing all of this memory, the same amount is no longer available.
Now, your first thought is probably that there is obviously a memory leak here! Well, there doesn't seem to be. I analysed my memory usage using
adb shell dumpsys meminfo (app package)
These are my results:
Before processing:
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 19736 19712 12 1268 36864 26663 10200
Dalvik Heap 15201 15176 0 3308 32992 16694 16298
During:
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 889826 889804 8 1252 929792 914480 15311
Dalvik Heap 16769 16744 0 3308 33678 18541 15137
After:
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 22234 22212 8 1252 45056 28468 16587
Dalvik Heap 16461 16436 0 3308 33871 17573 16298
Before and after aren't quite the same, but I also moved between activities in the mean time so there is noise.
It may also be the case that after processing data once, there is no longer a continuous block of memory available, but I still don't know how to avoid it.
I could possibly use a service in a separate process to do the jni stuff and kill the process afterwards, but I haven't tested this out so it might not work. Restarting the app and recreating the entire backstack seems to do the trick, though that might be quite hard to make completely stable, it will make things slower and I really don't want to do that.
Does anyone have any better ideas?
It turned out that the issue was that the released memory apparently had to be garbage collected.
While using using the meminfo call seemed to imply that all memory was released, the call itself triggered garbage collecting. After my processing had finished but before calling meminfo, the memory was not available.
I managed to get everything working alright by calling System.gc(). I know it's not recommended and is said to only be a suggestion to the system, but it genuinely seemed to fix the issue.
I cannot understand what is happening here - I have been creating a small project just to learn about rotation of an image. But this is not relevant here.
So - I have been doing this before and know how heap works, but right know I cannot get it.
In this small Eclipse project I put an image in the drawable-mdpi folder. The image is
1300 * 1950
So simply - this image will occupy about the following amount of ram (heap)
10 MB (1300 * 1950 * 4)
Red, gree, blue and Alpha. Thats it!
But what is happening. Well see the logcat below!!! the heap of 63 MB for my Samsung Galaxy S3 is almost exhausted.
02-17 08:50:05.144: I/dalvikvm-heap(21097): Grow heap (frag case) to 22.494MB for 10140016-byte allocation
02-17 08:50:05.164: D/dalvikvm(21097): GC_CONCURRENT freed 1K, 5% free 22152K/23175K, paused 12ms+2ms, total 22ms
02-17 08:50:05.329: D/dalvikvm(21097): GC_FOR_ALLOC freed 0K, 5% free 22152K/23175K, paused 11ms, total 11ms
02-17 08:50:05.429: I/dalvikvm-heap(21097): Grow heap (frag case) to 61.174MB for 40560016-byte allocation
02-17 08:50:05.449: D/dalvikvm(21097): GC_CONCURRENT freed 0K, 2% free 61761K/62791K, paused 11ms+3ms, total 22ms
02-17 08:50:06.109: D/libEGL(21097): loaded /system/lib/egl/libEGL_mali.so
02-17 08:50:06.119: D/libEGL(21097): loaded /system/lib/egl/libGLESv1_CM_mali.so
02-17 08:50:06.124: D/libEGL(21097): loaded /system/lib/egl/libGLESv2_mali.so
02-17 08:50:06.179: D/(21097): Device driver API match
02-17 08:50:06.179: D/(21097): Device driver API version: 10
02-17 08:50:06.179: D/(21097): User space API version: 10
02-17 08:50:06.179: D/(21097): mali: REVISION=Linux-r2p4-02rel0 BUILD_DATE=Fri Sep 28 10:42:56 KST 2012
02-17 08:50:06.254: D/OpenGLRenderer(21097): Enabling debug mode 0
First it allocates properly - you can see 10 MB (according to my calculations) and a heap well above that - that is 20 MB. So far so good. BUT THEN IT CONTINUES TO ALLOCATE MEMORY FAR ABOVE THAT LEVEL. Like there was another image of 40 MB (4 times the previous) so the allocated heap ends up in 61 MB, almost tangenting out of memory.
What did I miss here or is it a bug? I have checked all the drawable folders and I know I run this app and not another. I recreated the project to be sure, even changed the image name. restarted the computer AND the device
this is the source code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ImageView imgview = (ImageView) findViewById(R.id.image);
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
}
the xml-file
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
more info: The device is rooted
I have been looking to Logcat output for memory performance. With the given data below, how should I understand whether my app is increasing or releasing it? Is it an acceptable performance?
07-23 14:52:05.910: D/dalvikvm(4909): GC_CONCURRENT freed 1332K, 25% free 7791K/10300K, paused 3ms+3ms, total 45ms
07-23 14:52:06.170: D/dalvikvm(4909): GC_CONCURRENT freed 1230K, 25% free 7811K/10300K, paused 4ms+4ms, total 44ms
07-23 14:52:06.360: D/dalvikvm(4909): GC_CONCURRENT freed 1222K, 24% free 7887K/10300K, paused 3ms+4ms, total 53ms
07-23 14:53:08.610: D/dalvikvm(4909): GC_CONCURRENT freed 1315K, 22% free 8061K/10300K, paused 5ms+3ms, total 99ms
There is a monitor app that comes with the Android SDK. You can use to to look at the memory that your app is using. Take a look at this post on the Android Developers blog.
There is nothing intrinsically wrong with the log output.