前言
为了满足不同用户的多样性购物需求,过去两年里手机淘宝的业务不断膨胀,已经从单一的购物工具成为了购物内容平台。在业务快速增长的同时,也带来一些副作用,很多操作环节和页面因为承载功能太多,展示速度变慢,用户等待时间变长,性能优化势在必行。
通过大半年的摸索总结,从实践中我们得出了App性能优化的七大策略:
1.建立监控体系,善用分析工具
2.完善网络基础建设,不断调优
3.利用本地缓存,建立离线化
4.任务分级,合理并行,主线程移除多余操作
5.业务模块懒加载
6.优化页面结构和层次
7.做好图片下载缓存工作
首先是监控体系的建立:根据手机淘宝用户的操作习惯,我们对购物主要链路进行了划分,分为启动,首页,搜索,购物车,下单,支付环节,订单查看等七个环节,每个步骤和模块都做到监控,以量化数据为指导,有的放矢进行优化。
对于手机淘宝购物主要链路的七个业务环节,本文将抽取三个做重点介绍:启动、首页、购物车;然后针对网络调优,图片下载缓存两个基础能力的优化和如何善用分析工具来做详细介绍。
一.启动优化
通过线下分析工具,线上灰度数据和代码review,发现启动慢主要有三个原因:
-
提前引入了许多模块的初始化;
-
在主线程,存在耗时的非必要阻塞操作;
-
部分锁操作,导致主线程wait时间较长。
由此制定出优化的方案:
1)采用优化策略3--利用本地缓存,建立离线化
从用户点击图标到首页第一次展示,整个过程执行严格的无网策略,不做任何网络交互,所有数据通过缓存或预置的方式获取。
通过将耗时的网络IO操作后移,减少了时间开销。
2)采用优化策略4--任务分级,合理并行
将启动中的所有任务进行梳理和分级,根据级别来调整执行对应任务的时机:
-
一级:阻塞启动的任务,比如基础SDK的初始化,首页页面的创建等。
-
二级:可延迟到首页加载成功后再执行的任务,比如自动登录,配置信息和运营数据拉取等。
启动时只执行一级任务,二级任务延迟到启动完成后串行执行,一级任务必须没有锁操作,保证主线程不会被阻塞。
3)采用优化策略5--懒加载
优化前,启动过程存在很多业务的初始化操作;优化后,采用懒加载策略,真正使用时才进行初始化加载,同时懒加载机制可以结合缓存或预置数据的方式来达到更好的效果。
比如在手机淘宝的五个TAB中,优化前,启动时会将五个TAB对应的页面全部创建出来,而实际上只有首页可见,其他页面的创建,包括页面中业务逻辑的请求发送,都会对整个启动造成性能损耗。使用懒加载的方式优化后,启动只创建可见页面即首页,其它页面只在用户点击对应TAB时才进行创建显示,此优化一举减少了近0.5秒的耗时。
在上述三个主要策略的优化指导下,手机淘宝的启动流程图调整为如图1所示,主线程中启动阶段只保留了必要的初始化,其他非必要的操作都被懒加载或者异步化。
二.首页优化
作为曝光量最高的页面,快速打开,稳定可用,及时更新是三大目标。
在首页,展示的内容大致分为四类:
-
二级页面的入口,图标,标题和位置相对固定;
-
顶部的轮播图,作为不同运营模块或活动的入口;
-
根据用户身份运算出来的推荐商品,店铺
-
顶部的消息盒子入口,带未读消息数字图标。
不同的内容采用不同的处理策略:
对于第1,2类内容,采用策略3,即进行本地cache化工作,将入口文字图标缓存在本地。渲染时优先展示上次cache内容,即使遇到无网的情况,首页的整体框架页面和cache过的图片和文字都能绘制出来。
本地cache通过时间戳来保证版本内容的及时更新。
在今年双十二的活动中,手机淘宝率先推出了图标运营,通过更新云端上的配置,待客户端上前一次cache过期就自然过渡到此版本,给用户带来了惊喜。
对于第3类内容,采用策略6,优化页面结构和层次:推荐商品放在页面最下部,默认不显示,当用户滚动上滑时做拉取绘制,避免页面一次拉取数据内容过多。
对于第4类内容则采用策略5,即懒加载,在首屏其他内容完成基础绘制后,才调用接口拉取未读消息数量。
此外,首页数据量相对较大,这些数据的加载,解析,拼装都是非常耗时的,而目前主流手机都是多核处理器,可以充分利用多核优势,将这些耗时操作放在异步线程里完成,保证主线程正常调度。当数据准备完毕,才在主线程中进行UI的渲染更新,从而保障了主线程的流畅性。
三.购物车优化
购物车已经成为用户的“第二收藏夹”,用户通过多终端(PC,手机)不断更新购物车的内容。在本地建立缓存保存数据,及时展示给用户是提升打开购物车页面的必然手段。
但由于优惠规则和总价计算必须在服务端完成,客户端在更新购物车时,不但要拉取商品数量的变化,也要拉取总价的变化。
以往是采用主动刷新时全量更新的简单方法,现在优化为差量更新,不但流量减少,更有效地提升了拉取和刷新展示的速度。
四.网络优化
上面从三个业务环节讲述了优化策略,现在从基础服务角度来描述优化手段。主干互联网传输消耗的时间,主要包括三部分:DNS查找、TCP/TLS握手、数据传输。如何降低这三部分的耗时是网优的重要手段:
-
IP直连:
自行实现承载在HTTP协议上的DNS解析协议。能节省DNS查找时间,规避传统DNS可能存在的劫持问题。2013年业界曾经发生过一次公网DNS Server被攻击,手机淘宝未受任何影响。
-
建立长连接:
通过SPDY实现,减少TCP/TLS握手,降低建立连接成本。对于从CDN下载图片速度帮助很大。
-
域名收敛:
收敛域名至公司的主力CDN域名。将请求集中在少数几个域名下,以提高长连接的复用率.
-
TCP调优:
无线网络特点是丢包率高、RT长,针对此特点可以做针对性的TCP调优。
-
报文缩减:
逐步由JSON协议向类PB协议转换。
五.图片方面优化
图片是电商App使用场景中最多的元素,如何节省流量,快速渲染是电商App都非常关注的。
在建立长连接,域名收敛等网络优化之外,手机淘宝还建立图片的分级机制:按分辨率,质量,锐化,格式四个纬度,对同一张图片生成了不同组合的衍生文件。
设置了一系列匹配规则,针对不同的屏幕,机型,处理能力和网络环境,配置出合适的图片大小质量,保证图片既节省流量又满足用户视觉体验。
其中一个经验是当锐化程度高时,即使图片质量较低,图片色彩清晰度也都能让用户满意。
其中一个经验是当锐化程度高时,即使图片质量较低,图片色彩清晰度也都能让用户满意。
六.工欲善其事必先利其器
在整个手淘的启动优化过程中,系统的工具帮了我们很大的忙,Android的主要是自带的 TraceView工具,IOS 主要是Instruments自带的Time Profiler,System Trace等工具,它们都是数据采集和分析工具,主要用于分析应用程序中的hotspot,都非常强大。工具的具体使用方法不在本文论述范围内,但是这些工具都提供了程序中的所有线程使用状况,而且线程中的每一次的调用都可以看到具体的堆栈信息、耗时等详细信息。通过对这些调用的分析,就可以找到启动过程中相对耗时的调用。分析出具体的瓶颈点以后,就可以有针对性地进行具体优化了。
比如 手淘Android启动阶段以前有一个加密存储的模块,它会调用系统的SecretKeyFactory.getInstance()方法来生成加密的 key,我们是通过 TraceView 才发现这个函数调用会耗时300ms 以上,通过 TraceView看里面的调用堆栈发现它里面存在锁操作,所以比较耗时,找到这个瓶颈点之后,手淘Android调研了多种加密存储方式,最后换了一种比较轻量的加密存储模块,优化了该瓶颈点。
最后总结七大原则:
1.善用性能分析工具,建立监控体系
2.做好网络基础建设和网络调优
3.离线化,本地缓存
4.懒加载
5.任务分级,合理并行
6.在主线程移除多余操作
7.简化合并复杂视图