背景
看着as profiler
内存区域的曲线一直上涨,我陷入沉思,我就是切换了几个页面,加载了一堆瀑布流组件,为何内存直接起飞了呢。但是加载了这么多的图片,我又不知道那个吃掉了内存,也不可能找产品要图片啊,因为图片很多,不可能我自己一个个翻查看属性看分辨率。那我应该怎么找出元凶?
As Profiler
在开发环境中我们正常运行起来app之后,打开profiler
可以查看app使用的内存情况。
内存分为几个类型。
1)进程总内存占用: 53.5M
2)JavaHeap: 7.8M
3)NativeHeap:native层的so中调用malloc或new创建的内存22M
4)Graphics:OpenGL和SurfaceFlinger相关内存当前demo是没有使用,0M
5)Stack:线程栈——0.06M,我的demo没有开线程,默认的线程占用
6)Code:dex+so相关代码占用内存——15.7M
7)Other:官方也没有解释,这个迷之存在???
我们可以录制某个时间段的内存记录,做分析,比如as profiler。
点击左边的录制。
等待几秒后录制完成,as会自动处理结果,可以看到如下信息。还可以查看内存泄漏情况,这里就不做内存泄漏的分析,后面再讲。
我在这里发现排在第一的是bitmap,我只能看到他的实例的数目和内存占用大小,as没有提供导出bitmap的功能
,就算我知道bitmap占用很多,哪有如何,我只是知道多,但是不知道那个实例对应图片是什么,找元凶是不能靠猜的啊。
加个条件:On Android 2.3.3 (API level 10) and lower, the backing pixel data for a Bitmap is stored in native memory. It is separate from the Bitmap itself, which is stored in the Dalvik heap. The pixel data in native memory is not released in a predictable manner, potentially causing an application to briefly exceed its memory limits and crash. From Android 3.0 (API level 11) through Android 7.1 (API level 25), the pixel data is stored on the Dalvik heap along with the associated Bitmap. In Android 8.0 (API level 26), and higher, the Bitmap pixel data is stored in the native heap.
官方的机制,在8.0及以上进行优化,图片内存走native
,不占用当前进程堆内存。也就是你需要分析的话,得找8.0以下的设备,刚好公司的盒子是7.1.2的。下面用公司项目做演示,如何找到图片大头!
在低于8.0的设备上面做分析
这个是重点,相信大家找一个低于8.0的设备很容易。 然后就是提取内存数据的事情了。
大佬提供的脚本,直接dump + 转换成MAT可用格式。
脚本:android_dump_java_heap.sh 环境:Linux,MacOS. win用户这样可以做。在as录制内存之后,右键export
保存这个文件,然后使用hprof-conv命令转换成MAT可读格式。
使用方式:
hprof-conv as161110-heap.hprof new.hprof
//回车,如果没任何提示,则成功,如果没有配置adb环境,自己解决
完整的脚本,我电脑为例子
ANDROID_HOME=/Users/macos/Library/Android/sdk
ADB=${ANDROID_HOME}/platform-tools/adb
HPROF_CONV=${ANDROID_HOME}/platform-tools/hprof-conv
# customized functions
# dump droid heap
function droid_hd() {
PACKAGE_NAME="com.demo.android"
echo "${PACKAGE_NAME}"
TIME=$(date +"%Y%m%d_%H%M%S")
FILE_NAME="${PACKAGE_NAME}-${TIME}-heap.hprof"
PATH_IN_PHONE="/data/local/tmp/${FILE_NAME}"
${ADB} shell rm ${PATH_IN_PHONE} 2> /dev/null
echo "cause GC for ${PACKAGE_NAME}"
${ADB} shell pkill -l 10 ${PACKAGE_NAME}
echo "> dump heap for ${PACKAGE_NAME}"
${ADB} shell "am dumpheap ${PACKAGE_NAME} ${PATH_IN_PHONE}"
if [[ $? != 0 ]]; then
echo
${ADB} devices
echo "run command:"
echo "\e[38;5;82mexport ANDROID_SERIAL="
return
fi
# I don't want to... But it smees adb shell can't block untils it's done!
sleep 3
echo "> list heap for ${PATH_IN_PHONE}"
${ADB} shell ls -lh ${PATH_IN_PHONE}
echo "> pull to computer"
${ADB} pull ${PATH_IN_PHONE} ./
echo "> delete device copy"
${ADB} shell rm ${PATH_IN_PHONE}
echo "> hprof-conv it"
${HPROF_CONV} -z ${FILE_NAME} droid-${FILE_NAME}
echo "> remove tmp hprof"
mv -f droid-${FILE_NAME} ${FILE_NAME}
ls -lh ${FILE_NAME}
echo "done! file: \e[38;5;82m ${FILE_NAME}"
}
droid_hd
前置条件:
app正常运行,达到了你需要dump
内存的环境,比如分析某个页面,某操作之后。 进入sh所在的目录,运行
./android_dump_java_heap.sh
//如果权限不足可以提权
sudo chmod 777 android_dump_java_heap.sh
执行上面命令之后会走一次gc,然后dump内存数据转换好格式。 接下里就是MAT
登场了。
MAT提取大图片bitmap
Memory Analyzer (MAT)
下载地址:https://www.eclipse.org/mat/
如何使用,慢慢来吧,遇到什么不懂,就查。
快进到下载安装好MAT了,打开工具。
一个大概的分析图标。
然后我们打开Top Consumers,看看我们的图片大头。
恐怖如斯?,app运行一段时间后,总内存大概350这样,图片吃了150
长得帅网友可能就要吐槽了,150,晒晒水啦,我手机内存都16g的
假如你的设备只有512mb呢,你还会如此冷静.......
我目前面对的环境就是低内存,512,1g的用户,没有大于1g的用户,都是免费送的盒子啊,你还想我送个8g的比你咩,喵喵喵~
我们继续切换到Dominator Tree
,看提示:
List the biggest objects and what they keep alive
看看那个倒霉蛋还活着。
这个内存占用是字节,算下来就是9mb,8mb,6mb这样,也就是一个bitmap,我们把其中一个导出来。
随便选择排在前面的一个,然后右键,copy,save value to file。
选择一个地方保存.
后缀必须是.data
后缀必须是.data
后缀必须是.data
保存好之后,使用GIMP
软件打开,这个软件目前只有MacOS和Linux版本。
群文件有,也可以到官方网站下载。
打开文件的时候会提示这个框,必须输入bitmap的准确宽高
才打开,不然直接失败。
打开文件的时候会提示这个框,必须输入bitmap的准确宽高
才打开,不然直接失败。
打开文件的时候会提示这个框,必须输入bitmap的准确宽高
才打开,不然直接失败。
我们回去MAT中拿到bitmap的信息。
选中我们导出的对象,菜单:Window,Inspector,打开信息面板。
宽高拿到之后,在打开data文件的地方填写
一定要选择:alpha
,然后其他默认,写入宽高。open。就能看到谁吃了我们的内存。
如果你想分析其他大bitmap,同样操作就ok了。
如果上面要我们优化内存占用,我们就有一个小方向突破,比如找大图,问题是图片都是都是后台动态设置的,产品配置,ui给的,我们app只是负责加载,要是你一次性整几十张这样的大图,app很大可能oom,我们要甩锅,要拿出证据,上面就是分析提取证据的方法之一。剩下的事情我们只要买一包瓜子就行了。
总结
1,吃内存的到底是谁 2,我找到了内存占用的大头,怎么看它真面目 3,工具怎么使用 4,必须的环境:低于8.0,mat,gimp 5,有手✋?
不要被你的手机配置蒙蔽了你的双眼,用个低配的设备跑跑,你就知道你开发的软件有多卡~~,如有冒犯,顺着网线来打我吧~~
优化之路漫长,我会将我用在项目上的案例都分享给大家,如有错漏之处,希望能指正。
我是断点,很骚的断点。