一.背景
最近测试人员对我们的产品进程内存占用测试,并和竞品的内存占用情况进行对比,得出的结论是我们的产品占用的内存比竞品多出不少,
所以需要对产品进行内存优化,我主要负责对商店进程的内存进行优化,以下是优化的过程和优化结果的总结。
二.优化
设备:Samsung Galaxy S4
Android version:5.0
主要在下面五个场景来对内存占用情况进行分析并优化
场景1:首次安装进入设置页
首次安装,并进入设置页,该场景下内存的占用主要有三个方面:商业化SDK、第三方库、本地业务功能。
对于商业SDK我们无法进行优化,但第三方库和本地业务代码可以进行优化。
看到Glide库占用了大概4M左右,在商店进程中使用Glide主要是用来展示gif,可使用sketch作为替代方案
*优化方法:商店进程不使用Glide
优化结果:4.5M -> 0M 优化4M*
在进入设置页面后,有部分功能已经不再使用,但还是进行不少的内存分配。
主设置页的礼盒广告界面占用内存:
主设置页积分墙界面占用内存:
*优化方法:删除代码
优化结果:1.5M -> 0M 优化1.5M*
场景2:从设置页进入主题商店
提示:进入主题商店后不进行任何操作,待内存稳定后dump出heap的内存情况
进入主题商店后的内容有:在顶部一个Banner轮播图(五张banner,但一次只显示一张)、六张主题预览图
内存分配情况如下:主要集中在imageload和bean中
imageload中主要内存分配是图片的缓存,缓存了四张图片 ,其中一张是进入商店的伪全屏广告上的图片。剩下的三张是顶部Banner
分配的内存 1.45*3 = 4.3M
上面缓存的图片是来自顶部Banner和广告上的图片,其中广告上的图片是一张(先忽略)。启动剩下的三张都是Banner的。
在只显示一张Banner的情况下,缓存了三张Banner的原因:1张正在展示的Banner,2张预加载的Banner(正在展示banner的左右各一张)
提示:由于顶部的Banner是使用viewpage实现,而viewpage默认是会进行预加载的。
*优化方法:Banner只预加载右边的一张(进入主题商店),使用Sketch代替Volley进行图片加载
优化结果:4.3M -> 1.4M 优化2.9M*
上面说的图片缓存中有缓存广告图片,而缓存这个广告图片是没有意义,因为广告展示一次以后就会重新去拉取新的广告,新的广告图片又是不一样。
而目前我们的商店进程中的广告在展示时都是会对图片进行缓存的。由于我们涉及到的广告比较多,对这些广告进行修改和测试的成本比较高
目前修改了进入商店的伪全屏广告的离线广告源进行修改
*优化方法:广告上的图片不进行内存级别的缓存,只进行磁盘缓存, 使用Sketch代替Volley进行图片加载, 同时也不把不再使用的广告图片放入BitmapPool中,这样可以一张广告图片可少占用350K
优化结果:1.4M -> 0.35M 优化1M*
bean中存放的是商店的实体数据,在第一次进入到主题商店,还未进行任何滑动操作,实体数据就占用了2.5M
如果在主题商店中进行滑动操作,多请求两页,实体数据的内存占用情况如下
一下子来到了5.9M,而这些实体类中都是些字符串,所以还是存在很大的优化空间的。
商店实体类中冗余信息很多,商店实体数据优化的空间很大,但工作量也不小,目前只对主题商店进行优化,贴图商店的实体数据未进行优化
优化有的实体类内存占用来到了560K左右
*优化方法:去除主题商店冗余信息
优化结果:2.6M -> 0.56M 优化2M*
场景3:在主题商店中滑动操作,使得全部主题预览图都加载并显示出来
使用Sketch加载尽可能多的图片,看看内存的分配情况,商店进程总的内存一直保持在160M上下波动,说明Sketch的缓存已满。
Sketch的内部包含一个Bitmap内存缓存和一个Bitmap重用缓冲区
对于该测试的设备
Bitmap内存缓存的最大内存:24883200
Bitmap重用缓冲区最大内存:24883200
都使用24M的大小。
加载完预览图片后,待内存稳定后,两个缓存区占用的实际内存大小如下:
目前这两个缓存区的最大值的计算方式大概如下:
计算出系统为每个进程可用的大概内存TotalMem
高版本设备 MaxSize = TotalMem * 0.4
低版本设备 MaxSize = TotalMem * 0.33
然后大概就是 BitmapPool和MemoryCache平分MaxSize
由于BitmapPool和MemoryCahce缓存最大值在不影响体验的情况下可设定小一些。但目前还没有找到设定缓存区大小的接口,所以目前未对这一部分进行优化。
解决的办法是找到源码,修改后重新编译打个包,目前源码已经找到,但还未进行修改,这个放到第二阶段再优化。
我们可以控制一些不可能重用的图片不放入到BitmapPool来减小BitmapPool类存占用,比如商店顶部Banner和广告上的图片。
测试的方法是进入到主题商店后,加载完Banner和进入主题商店伪全屏的离线广告后,退出到设置页,查看BitmapPool的缓存情况
优化方法:广告上的Bitmap和商店顶部Banner在销毁时不放入BitmapPool
优化结果:1.2M(顶部Banner) + 0.35M(进入商店伪全屏离线广告) -> 0M 优化1.5M
场景4:从场景3回到设置页面
在场景3时,内存占用稳定在160上下。如下:
退出到设置页后内存才减低了10M左右,很不科学。
主要还是Sketch的缓存区还未进行释放
于是在退出商店后,主动去清除一些缓存,保证LruBitmapPool和LruMemoryCache两个缓存区占用的内存不大于最大值得一半。优化后的内存占用情况
*优化方法:返回到设置页时回收LruBitmapPool和LruMemoryCache部分内存
优化结果:40M -> 24M 优化15M*
三.总结
目前的优化工作只对主题商店和贴图商店模块进行优化,因为这两个模块图片比较多,优化空间比较大。到目前为止优化的效果如下:
* 用户第一次安装启动,并进入进入设置页:优化5.5M
* 用户第一次安装启动,并从设置页进入主题商店:优化5.9M
* 在商店总进行滑动,加载全部的主题图片(包括贴图):优化1.5M
* 当主题的图片全部加载完成后,返回到设置页:优化15M(这个优化内存值不确定)
如下的几个模块还未进行检查,所以也不知道是否有优化的空间:
* 键盘背景设置模块
* 按键音设置模块
* 字体下载应用模块
* Emoji商店模块
* 贴图商店ZIP下载模块
还存在一些点可深入优化,且效果会比较好。如下几点:
* 商店数据实体类数据结构优化(优化空间很大)
* 广告上的图片加载方案使用Sketch替代,且不进行内存缓存(工作量比较大,测试工作也也很大)
* 主题商店中的分类、壁纸、Go Family的图片加载使用Sketch替代
* 贴图商店中的详情页图片加载使用Sketch替代