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.
Related
Nearby I noticed that my Android app often crash because of OOM.
I use Android Studio 3.2.3 Profiler, so I find that native heap are up to 300M.
I want to find the memeory use by every C++ so files, BUT I can not find a tool to accomplish my work.
Any advice is appreciated
adb shell dumpsys mypackage
App Summary
Pss(KB)
------
Java Heap: 11568
Native Heap: 202176
Code: 18576
Stack: 2716
Graphics: 84772
Private Other: 11300
System: 43414
TOTAL USS: 331108
TOTAL: 343727 TOTAL SWAP PSS: 30795
My Android project gets built fine on a Windows dev machine with lots of RAM. But in a simple Docker container (FROM ubuntu:xenial + Android SDK) gradle build (./gradlew assembleTrunkDebug) fails on 58% while executing the task:
transformClassesWithPreJackPackagedLibrariesForTrunkDebug
Even with --stacktrace --debug the most I get from the error is:
Gradle build daemon disappeared unexpectedly (it may have been killed or may have crashed)
There are several strange thing that I have noticed:
It doesn't matter what memory arguments I'm passing to the docker container instantiation. It always shows me the same memory stats.
Tasks: 2 total, 1 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1019776 total, 860604 free, 88840 used, 70332 buff/cache
KiB Swap: 1168688 total, 853640 free, 315048 used. 824484 avail Mem
I'm usually doing something like:
docker run -it --volume=/Users/MyUser/code/localDebugRepo:/localDebugRepo --workdir="/localDebugRepo" --memory="2048m" --memory-swap="2048m" 66b48030ee34 /bin/bash
But I have also tried to pass less memory and the same memory-swap or more total memory, but it always shows me Mem: 1019776 and Swap: 1168688.
I also noticed in the task manager that VBoxHeadless.exe uses only 41MB of RAM. While the misfortunate task is running (which takes a long time before crashing), the RAM usage doesn't change, but the Disk transfer is huge and only consumes more and more (since it's on SSD drive).
Android suggests the new build tool Jack and Jill used for the latest sdks has to be allowed to use at least 1536m memory. But the Docker image should run with max of 2048m and having in mind that I wasn't able to shrink the swap, I have the feeling something goes wrong there.
So any thoughts what might have caused this consistent error?
I'm currently working on a hybrid application that is exhibiting some peculiar memory usage that I'm trying to debug. As soon as the application starts, it appears to be immediately using close to 250MB of memory, which seems excessively given that all we have loaded at that point is the login screen. I've been looking at a few memory profiling tools for Android (the Xamarin profiler and the android profiler shipped with the SDK), but all of them show relatively low heap usage (~10-15MB, which I'm trying to get down). I ran "adb shell dumpsys meminfo APPNAME -d' and got the following trace:
** MEMINFO in pid 24925 [APPNAME] **
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 19439 19396 0 0 28672 22915 5756
Dalvik Heap 15441 14992 0 0 37319 36837 482
Dalvik Other 542 368 0 0
Stack 432 432 0 0
Ashmem 17388 16508 880 0
Gfx dev 40538 34504 0 0
Other dev 4 0 4 0
.so mmap 6211 224 3080 0
.apk mmap 10531 0 10232 0
.ttf mmap 453 0 260 0
.dex mmap 1263 0 980 0
.oat mmap 635 0 152 0
.art mmap 707 516 24 0
Other mmap 452 4 52 0
EGL mtrack 63508 63508 0 0
GL mtrack 79116 79116 0 0
Unknown 21756 21756 0 0
TOTAL 278416 251324 15664 0 65991 59752 6238
I've been trying to understand what this means by using the documentation provided at: https://developer.android.com/tools/debugging/debugging-memory.html, but that page doesn't seem to have any info on the biggest culprits: Gfx dev, EGL mtrack, GL mtrack, and Unknown. Is there some documentation on what these categories are or why they would grow to be so big?
Thanks
EGL and GL shows here memory consumed by Graphics layer basically. I am sure you are running adb shell dumpsys meminfo command on Android lollipop device. Actually dumpsys meminfo tool/command has been modified in lollipop to calculate and display graphics memory.
In old version (KitKat or older) you can not find EGL and GL information although graphics consumed memory in KitKat or older versions also.
This is we can request Google to update their documentation to explain new memory components also. In short you can say it is bug in documentation of Android. They should update it as per latest implementation of adb shell dumpsys meminfo tool/command.
References:
EGL - http://en.wikipedia.org/wiki/EGL_(API)
GL - http://en.wikipedia.org/wiki/OpenGL
GL mtrack is driver-reported GL memory usage. It's primarily the sum of GL texture sizes, GL command buffers, fixed global driver RAM overheads, etc.
EGL mtrack is gralloc memory usage. It's primarily the sum of the SurfaceView/TextureView.
When I run "adb shell dumpsys meminfo" on android 4.2, I get the result like
Shared Private Heap Heap Heap
Pss Dirty Dirty Size Alloc Free
------ ------ ------ ------ ------ ------
Native 28 8 28 16404 12256 3663
Dalvik 14062 10060 13736 20032 15254 4778
Cursor 0 0 0
Ashmem 0 0 0
Other dev 4762 9556 0
.so mmap 11699 1824 1500
.jar mmap 0 0 0
.apk mmap 368 0 0
.ttf mmap 811 0 0
.dex mmap 3736 0 0
Other mmap 114 16 32
Unknown 12064 544 12052
TOTAL 47644 22008 27348 36436 27510 8441
I have read the page of How do I discover memory usage of my application in Android?, but still have several questions:
Why the native Pss, shared dirty private dirty is very small?
the heap size should be smaller than Pss?
What does Unknown mean? Seems very big.
If I want to know how much memory my app uses, which data should I use? The Total Pss? But it doesn't include the native Pss which is nealy zero?
Please refer to the question How do I discover memory usage of my application in Android?.
I would also like you to refer to Detail VSS,RSS,PSS,USS link. The most appropriate data to use for a particular app is
USS (Unique Set Size ) as
USS is the total private memory for a process, i.e. that memory that is completely unique to that process . USS is an extremely useful number because it indicates the true incremental cost of running a particular process. When a process is killed, the USS is the total memory that is actually returned to the system. USS is the best number to watch when initially suspicious of memory leaks in a process.
which you can get by adb shell procrank | grep <your.package.name>
I would like to know how I can troubleshoot high memory usage problems of my app on Android. I've search the internet and found out that the DDMS plugin is useful in taking a memory dump of the heap for my app. This however has been useless.
The app "Usage Timelines Free" is showing 94 MBs of memory used, while the DDMS heap dump shows me a total of 8.4 MBs, with the suspected leaks being the resource files.
When I generate a dump from adb (dumpsys meminfo), I get:
Shared Private Heap Heap Heap
Pss Dirty Dirty Size Alloc Free
------ ------ ------ ------ ------ ------
Native 20 8 20 54588 39431 1892
Dalvik 6732 9952 6396 10756 10028 728
Cursor 0 0 0
Ashmem 184 0 184
Other dev 11462 1172 11384
.so mmap 2467 2072 1156
.jar mmap 0 0 0
.apk mmap 48 0 0
.ttf mmap 2 0 0
.dex mmap 1037 0 0
Other mmap 41 16 32
Unknown 46352 292 46348
TOTAL 68345 13512 65520 65344 49459 2620
How can I know what is behind this huge memory consumption. My app is a foreground monitor service which runs forever, with a few activities which are accessed a few times per day.
Thanks.
Minimize your android data usage. Check the link :http://engineroots.games4punk.com/minimize-your-android-data-usage/
DDMS and got a heap memory dump. It only showed 8.4 MBs being used!
Then you are only using 8.4MB of heap space after a complete garbage collection (a net effect of creating the heap dump).
Note that if you ran this on Android 1.x/2.x, MAT will not report space consumed by bitmaps. Always try to dump the heap from an Android 3.0+ device or emulator.
When I generate a dump from adb (dumpsys meminfo), I get:
My guess is that you are running this on an Android 1.x/2.x device or emulator, and you have a lot of bitmap memory. Try running your heap dump and other tests on an Android 3.0+ environment.
Also, bear in mind that adb dumpsys meminfo does not perform a complete garbage collection, whereas dumping the HPROF file does. The Android garbage collector is optimized to minimize CPU utilization and therefore does not attempt to perform a complete garbage collection. Hence, at runtime, the heap is usually filled with garbage that will be reclaimed, as needed, by the GC engine.
You might also wish to read Dianne Hackborn's essay on this subject.