基于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的参数,早点杀掉退到后台的进程。限制cache进程的数目。

  开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等等

总结

以上介绍了内存优化的流程,很多都是以内存为目标,这个还是有点太狭隘,最终目标的用户体验,如果用户体验不好,那么你优化的措施就不能实施,所以大家在做内存优化的时候要多关注一下性能问题

三、Kernel层

针对系统剩余内存方向出发

1 针对文件页和匿名页回收,增加swapiness. 尽量使用匿名页回收。

2 zram的使用。尽量将不常用的应用放入内存。!!!

3 proc/meminfo中的Mlocked的页尽量去掉。 建议关闭。

4 配置MALLOC_SVELTE :=true 来disable tcache.  目前系统默认使用的是jemalloc

[DESCRIPTION]

KK及以前版本默认使用dlmalloc,没有其他选择,从L开始,引入了jemalloc,并且作为默认的内存分配器。jemalloc在多线程环境下性能好于dlmalloc,不过调试比较困难。有时为了调试需要将jemalloc切换为dlmalloc。以下提供切换方法。

[SOLUTION]

有2个地方可以切换,效果一样:第1个地方:/device/$company/$project/BoardConfig.mk添加:

MALLOC_IMPL:= dlmalloc

第2个地方:/device/mediatek/$project/ProjectConfig.mk添加:

MALLOC_IMPL= dlmalloc

其中$company为对应公司名,$project为项目名。

MALLOC_IMPL值可以为dlmalloc或jemalloc,如果没有定义MALLOC_IMPL则默认为jemalloc。

底层内存裁剪的一些思路:

主要思路是针对功能需求,裁剪冗余或无用的功能项,可以从以下几个方面下手:

1、kernel config的逐个排查,去掉冗余的项

结合功能需求去掉无用的功能模块,非必要的调试选项,比如安全/加密部分,USB的多余外设支持,FS的多余支持

2、缩减reserved的内存占用

从dts中声明 reserved 或代码中申请reserved的部分下手

3、缩减未进入内存管理的内存占用

找出物理内存 - MemTotal(/proc/meminfo中第一行)被哪些地方使用, 看能否裁剪一些

4、从占用较大的内存块下手,找到谁在使用, 看能否裁剪一些

/proc/vmallocinfo 中较大的部分

/proc/slabinfo 中较大的部分

5.从多余的native进程下手

从adb shell ps -A中排查非必要的进程和服务,进行裁剪

如何查看kernel占用的内存:

1、未进入内存管理的内存

即是物理内存 - MemTotal(/proc/meminfo中第一行)的部分。

2、kernel reserved内存

kernel reserved的内存,即是kernel log中Memory:的reserved部分的大小

举例如下:

//代码占用 = kernel code + rwdata + rodata + init + bss//reserved = reserved + cma-reserved//关系:reserved_pages(63776K) = physpages(2045952K) - totalram_pages(1982176K) - totalcma_pages(0K)[0.000000]-(0)[0:swapper]Memory:1982176K/2045952K available(12924K kernel code,1384K rwdata,4392K rodata,960K init,5936K bss,63776K reserved,0K cma-reserved)

3、kernel运行中分配的内存

对应dumpsys meminfo 中Used RAM:中kernel部分的大小

这里kernel的占用是从/proc/meminfo和/proc/vmallocinfo中统计而来,具体上:

kernel used = Shmem + SUnreclaim + VmallocUsed + PageTables + KernelStack

Shmem,SUnreclaim,PageTables,KernelStack对应/proc/meminfo中的具体字段

VmallocUsed 是统计/proc/vmallocinfo中除ioremap,map_lowmem,vm_map_ram之外的和

Total RAM:1,983,136K(status critical)Free RAM:1,116,972K(0K cached pss+203,672K cached kernel+913,300K free)Used RAM:873,491K(629,723K used pss+243,768K kernel)Lost RAM:-7,331K ZRAM:4K physical usedfor0K in swap(1,048,572K total swap)Tuning:128(large256),oom322,560K,restore limit107,520K(high-end-gfx)

你可能感兴趣的:(基于Android内存裁剪)