基于Android内存裁剪
最近身边朋友参与车载项目或者手机项目的,他们都面对一个问题就是为了节约成本,降低内存.我目前碰到两个案例,一个车载项目Android8.0 计划从2GB降低到512MB, 另一个是Android6.0的手机项目.
所以针对这类需求我们应该如何下手呢?内存裁剪的目标是什么呢,占用越少越好?
目标
我们先回答第二个问题,我们裁剪内存的目标是多少呢?根据Android go的建议,针对512MB的设备有一个推荐,大家可以参考一下下面的截图。
通过上面我们大致清楚我们的优化目标了,考虑到google会集成进去gms app,这块会占用50-100MB内存.那么多针对HVGA和WVGA的设备,在抛开GMS的情况,设备差不多目标能够在200MB左右即可满足. 当然设备不同,需求不同,内存也不一样,比如车载设备没有NFC,即可节约30MB常驻内存,没有modem可以节约80MB等等,所以后面具体问题具体分析。
怎么做呢?
第一: 确认当前内存的使用情况
1.读取物理硬件的内存占用
adb shell cat /proc/meminfo读取出MemTotal的大小,用总的内存大小减去这个Memtoal就得出物理设备占用的大小,如果想知道这块具体分配情况,有两个办法:
A.通过读取串口log,每次串口开机时候都会打印出来内存分布情况
B.在lk或者高通的amss代码里面有相关源码可以参考,具体咨询底层或者芯片厂商
2.读取开机到launcher的内存占用情况
Android提供一个命令dumpsys,可以执行adb shell dumpsys meminfo,比如下面的结果:
通过上面图标可以看出整体的内存分配情况,基本上可以分为几类:A.常驻内存进程,不开被回收(Native) B.需要常驻内存,但是可以被回收,杀掉的话影响UE体验(Forground,Visibile,Perceptible,A services,Previous) B.可回收内存进程 (B service,Cached app)
第二: 针对内存使用情况进行当前设备的需求分析
我们针对上文内存占用情况进行分析,我们内存裁剪主要从三个方面着手:
1.分析硬件模块需求,调整物理模块的内存占用
就个人经验来看,底层很多内存都不怎么使用,而预留了,比如说NFC,很多项目不支持,而硬件也预留了,比如bootlogo这块,有些项目不需要这个
2. 针对常驻内存做内存优化和裁剪
比如某些常驻内存的service不怎么经常使用,却一直占据后台,改变内存分配方式节约内存(MALLOC_SEVLTE)等等
3.早点释放后台进程内存,增加内存扩展
调整LMK的参数,早点杀掉退到后台的进程。
开ZRAM,增加内存
第三: 已知的可以优化或者裁剪方案
1.设置设备为low ram
改善了内存管理
减少了系统内存占用
具体参考: https://source.android.com/devices/tech/perf/low-ram
2.64位改成32位
据内部测试来看,内存可以节约20%左右
3.改变内存分配方式,je malloc
MALLOC_SVELTE := true
4. 打开ZRAM
5.调整dalvik参数
6.调整lmk参数
目前go用的lmkd管理,不再按照之前按照内存剩余级别杀掉进程
7.其它native模块的裁剪或者优化
比如camera优化,具体和项目的camera负责人员沟通
8.system_server裁剪和优化
systemserver进程中会启动很多service,里面还有几个运行宏,可以动态关闭,不过需要修改代码,我关闭了大部分,开不了机器,修改了很多代码才能开机,不过还是能节约部分内存的。
8.app优化
很多app不仅仅提供ui功能,还要provider功能,这样导致部分app在退出到后台后进程优先级还是比较高,很难被lmk回收掉,这种情况我们可以把provider和ui部分隔离开来,当然系统中很多这样的案例,Settings和SettingsProvider
还有些app开机就启动,并且绑定核心service或者指定persistent属性不能被杀掉,比如nfc进程,这种情况可以分析代码逻辑,开机不让其启动。
9.其它优化
每个项目的需求不一样,大家根据自己的项目需求可以裁剪一下其它的,比如有些对launcher不看中,那就换一个简单一点的launcher,有的项目部需要systemui,那就拿掉systemui等等
总结
以上介绍了内存优化的流程,很多都是以内存为目标,这个还是有点太狭隘,最终目标的用户体验,如果用户体验不好,那么你优化的措施就不能实施,所以大家在做内存优化的时候要多关注一下性能问题