2015年是全面『无线化』的一年,在BAT(财报)几家公司都已经超过50%的流量来自移动端,这次 双11更是占到了68.67%无线交易 (天猫微博)。
手淘中大量的业务采用H5的方式开发,H5体验好坏全面影响着手淘的使用体验。
今年手机淘宝在技术上重点解决“顿”,“卡”,“慢”的问题,并提出了“521法则” ,具体指:
App内存节省50%绘制帧率,滑动体验提升20%App全链路实现 1S 法则 强网(4G/Wifi)实现1S首屏(包括图片)加载3G 1S首包返回2G 1S建连,并且实现高复用 从底层到前端其中1S加载完成是H5页面需要解决的重点问题,也是难点。
下面给大家介绍我们1年多来解决了些什么样的问题,以及带来多少性能的提升。以下每一条都是手淘在无线领域获得的宝贵经验。
首先给大家介绍一下目前手淘的环境情况(供大家在设备兼容方面参考)。
操作系统方面iOS占比42.23%,Android 占比52.38%,阿里云OS 占比5.29%,Windows Phone 占比 0.1%。
iOS 系统版本占比情况:
iOS 9 49%iOS 8 38%iOS 7 11%Android 系统版本对比iOS 碎片化较为严重,所幸4.0以下版本占比小于10%。
占比如下:
4.4.4版本30%4.4.2版本16%4.3版本11%4.2.2版本10%5.0版本以上10%网络情况方面,得力于近年的3G/4G推广已经占35%,2G网络占比15%左右。
运营商方面 中国移动占据70%的用户,中国联通18.12%,中国电信11.69%。其中需要注意的是移动3G技术(TD-SCDMA)性能差设备支持少,移动4G容易在信号不理想的地段降级成2G。
淘系H5页面主要在手淘客户端中展现,为了了解H5页面在客户端中的性能表现,我们在WebView容器中做了大量性能数据的采集,以页面,数据接口,单个静态资源为维度采集。
H5页面:我们以WebView的DidFinishLoad事件触发作为完成加载(Fully Loaded)的时间。
同时对支持performance.timing的设备收集Timing数据,用于详细分析网络请求各阶段的性能消耗情况。
WebViewDidFinishLoad 官方解释:Sent after a web view finishes loading a frame. [Android](http://developer.android.com/reference/android/webkit/WebViewClient.html#onPageFinished(android.webkit.WebView, java.lang.String)) iOS
针对几个主要的业务,我们将收集到的用户性能数据整理后得到以下的结果(部分业务按传统的网页性能优化方法优化过)。
性能情况非常不理想,不达标严重。2G下大于10s的占比在50%, 3G:6s内的低于70%近一半。
看到上面的性能情况,我们最先想到的优化方法就是PC时代YAHOO 23条web性能优化军规。
首先看看我们日常业务的请求瀑布图是怎么样的,根据这些情况看那些可以用规则去优化。
iconfont对于前端来说有很多优点:自由变化大小 矢量不失真、自由修改颜色、可以添加一些视觉效果如 阴影、旋转、透明度、兼容IE6。
目前大家都基本上从平台上生成,生成后的文件如下:
@font-face { font-family: "iconfont"; src: url('iconfont.eot'); /* IE9*/ src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('iconfont.woff') format('woff'), /* chrome、firefox */ url('iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/ url('iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */}`
这样直接引用在项目中,真实在手机上的网络请求如下(在桌面版Chrome浏览器网络中无法看到这些请求):
这样造成了极大的网络带宽的消耗,这些icon资源往往在界面渲染中占据重要位置。 目前我们移动端只加载ttf一个字体文件,对于较小的文件也可以考虑base64在css文件中。
日常的业务中,一个页面往往拆分出多个异步数据接口(后端开发说:解耦),甚至首屏也需要3-5个接口(如动态banner区块,推荐内容,商品列表等),有些还有嵌套关系。 但是这些对页面性能造成不小的影响。
手淘中某个接口在各网络下的请求性能,2G,3G下平均的消耗时间在2-6s完成下载。其中几个请求性能稍差点对整个页面影响也深远。
在我们CaseByCase的分析中发现,页面&静态资源的重定向会造成巨大的性能损耗。 特别使用前端JS脚本来实现页面跳转的。
手淘的特点就是图片多,图片的性能好坏可不仅仅影响用户体验哦,还直接影响着交易,钱 钱 钱… 我们在图片方面做了大量的优化。
手淘2年前已经开始使用WebP格式了(主要native使用),1年前H5全面使用,其中iOS 的webview中由手淘以插件的方式支持。我们以手淘线上真实案例来看使用webp格式的前后效果。 案例为:线上的一个活动页面,打开一看其中的banner 就320多KB,整个页面加载457KB,如果就单单banner图片换成webp格式,整个页面的大小就只有181KB。
使用WebP前
使用WebP后
Banner部分对比
这种业务类型的案例,我们改进一下就可以为用户,为公司省70%的流量费用。
商品图片在手淘的各个产品中都是必不可少的,为了适应不同业务需求的需要,我们在CDN服务上生成各个尺寸和质量的图片(近100个规格)。
q值:根据手淘网络情况,加载不同质量的商品图片(q30,q50,q75,q90)锐化:根据需要调整图片锐化值DPI:根据设备DPI取适当尺寸商品图片合理的使用CDN图片尺寸可以带来下载图片的性能提升,还可以减少不必要的内存消耗。 我们日常中会用到的尺寸,每浪费10像素的宽高都可以造成很大的内存资源浪费。计算方式如下:
根据设备DPI值和图片质量Q值做优化,达到最优视觉体验和加载性能(DPI高,宽高增加后可适当降低质量)。
Sprite图片(又称:雪碧图)被运用在众多使用了很多小图标的网站上。相对于把每张小图标以单个文件的形式引用到页面上,Sprite图片会只要请求一张图片就够了,减少了请求数提升了加载性能,还有就是方便图标管理。但在移动互联网时代在使用Sprite图片需要合理利用,不然反对性能造成影响。
Decoded in memory的计算公式: w x h x 4(宽 x 高 x 每个像素4个字节) 如果设备DPI大于1,还需要 X DPI系数。如Retina设备X 4,RetinaHD设备X 9.
由于图片在浏览器中的解码方式,合理的生成紧凑的Sprite图片,即可以带来更少的请求数,又高性能低消耗。
经过几轮的常规前端性能优化后,页面性能有进步,但是离目标还远远不够。我们也不断的问自己到到底那里慢,那里瓶颈最大。我们开始试着CaseByCase的分析页以及梳理H5在手淘中的全链路性能消耗。
最终做了一些和native结合的优化思路。
DNS解析想必大家都知道,在传统PC时代DNS Lookup基本在几十ms内。而我们通过大量的数据采集和真实网络抓包分析(存在DNS解析的请求),DNS的消耗相当可观,2G网络大量5-10s,3G网络平均也要3-5s。
案例:iPhone5s 联通3G
针对这种情况,手淘开发了一套httpdns,httpdns是面向无线端的域名解析服务,与传统走UDP协议的DNS不同,httpdns基于HTTP协议。 基于HTTP的域名解析,减少域名解析部分的时间并解决DNS劫持的问题。
手淘httpdns服务在启动的时候就会对白名单的域名进行域名解析,返回对应服务的最近ip(各运营商),端口号,协议类型,心跳 等信息。
传统DNS由Local DNS解析域名,不同运营商的Local DNS有不同的策略,某些Local DNS可能会劫持特定的域名。采用httpdns能够绕过Local DNS,避免被劫持;另外,httpdns的解析结果包含HMAC校验,也能够防止解析结果被中间网络设备窜改。
更精准的调度对域名解析而言,尤其是CDN域名,解析得到的IP应该更靠近客户端的地区和运营商,这样才能有更快的网络访问速度。然而,由于运营商策略的多样性,其推送的Local DNS可能和客户端不在同一个地区,这时得到的解析结果可能不是最优的。httpdns能够得到客户端的出口网关IP,从而能够更准确地判断客户端的地区和运营商,得到更精准的解析结果。
更小的解析延迟和波动在2G/3G这种移动网络下,DNS解析的延迟和波动都比较大。就单次解析请求而言,httpdns不会比传统的DNS更快,但通过httpdns客户端SDK的配合,总体而言,能够显著降低解析延迟和波动。httpdns客户端SDK有几个特性:预解析、多域名解析、TTL缓存和异步请求。
额外的域名相关信息传统DNS的解析结果只有ip,httpdns的解析结果采用JSON格式,除了ip外,还支持其它域名相关的信息,比如端口、spdy协议等。利用这些额外的信息,APP可以启用或停止某个功能,甚至利用httpdns来做灰度发布,通过httpdns控制灰度的比例。
在经过以上的优化方案后,H5页面的性能始终离目标还远。在移动端建连的消耗非常大,在业界也只有SPDY 这个玩意儿比较新颖。 理论上SPDY协议可以完成多路复用的加密全双工通道,显著提升非wifi环境下的网络体验。
多路复用请求优化服务器推送技术SPDY压缩http头看着很牛逼的技术,但是等我们第一期上线后发现,从数据上几乎察觉不了变化。
域名收敛是指尽量控制一个页面中使用的域名数量。为什么要这么做呢?我们前面提到DNS解析,减少域名数量可以降低DNS解析的成本。上文还提到SPDY协议,其中一个特性就是复用请求,使用同一个域名可以更多的复用请求。这个PC时代正好相反,我们原先用多个域名提升并发请求量已提升性能。 PC时代的域名数量类似这样的
最终结合SSL+SPDY+域名收敛 才发挥出真正的作用。下图是各网络下SSL 和 非SSL 的性能情况。
动态数据部分,相信各个公司都差不多,动态数据会有专门的API提供出来。手淘(mtop平台)也一样,接口总会有各种状态,登录失效,令牌过期,签名失效等。手淘使用了重发请求的方式来获取新的签名令牌等。导致如下的情况(始料未及): 在手淘真实环境中发现一次令牌过期,可以造成10多秒的延迟。
手淘在启动的时候Native已经做了很多的数据请求,这些也是mtop请求,只是由native程序发出。 我们判断到页面是在手淘客户端中就会使用native发出mtop数据请求,这样就规避了令牌失效,签名失效的问题。
直本次优化后,我们第一次看到了非常激动人心的数据:第一次里程碑式的提升
优化前
优化后
手淘中加载H5页面的首屏白屏时间较长,基于此,集团各BU都内部产生了离线包的方案(手淘,航旅,钱包),将静态资源通过Hybrid的方式提前加载到本地。大量了资源预加载给H5页面带来了极大的提升,资源加载时间降到30ms内。 今年双11前,针对预加载方案,在技术上解决了3个痛点
开发成本(开发方式侵入性强)静态资源解Combo更新到达率关于 预加载&离线化方案详细技术细节很多,这里先简单阐述这个功能带来的性能提升价值。
下图案例:
第一个HTML没有预加载,阻塞页面时间较长静态资源部分几ms 级别加载,加载性能非常好这是第二次里程碑式的提升,3G,4G,WIFI网络性能全面提升。
截至到这个时间点为止,我们个别业务的性能有了显著的提升。以下是其中一个业务的3个性能优化节点的性能优化对比。其中10s以上加载完成的占比大大的缩小,1s以内的占比上升较高。
业务数据统计在日常工作中是必不可少的部分,因统计部分量级不大,往往会忽视掉。其中我们对一个业务CaseByCase的分析后发现。一个中国移动 2G/3G.Edge的用户在请求H5页面的时候 log.mmstat.com 的日志埋点花了近6s才加载完成。
后面我们对数据统计部分做了Native的异步上传。效果是这样滴:
iOS:
Android:
第三次里程碑式的提升,2G网络性能全面提升
前面说了这么多性能优化,肯定会有问,花了这么多力气,前端到客户端到后端搞了这么多,价值在那里呢。业界google,amazon,microsoft都给过速度性能对业务对GMV的影响。 下面是两个手淘中的业务在持续几个月的性能优化后UV,跳失率,停留时间的变化。
好了,说了这么多这次双11搞的怎么样呢?
在无线时代,H5页面中的任意一个微小的点都会应网络问题被放大N倍。持续分析用户真实数据和CaseByCase的分析不同业务场景,才能真正找到性能瓶颈。
H5要达到极致的体验,需要大家跳出前端的圈子,从客户端,后端 一起的角度来共同协助发挥各自的优势才能真正做到极致的体验。后面有更多精彩等这大家。
Contributor hongru commented on 23 Nov 2015沙发,最大的感触是“性能的问题,从10做到1,和从1做到0,是两个概念”
skylerzhang commented on 23 Nov 2015留名
whq731 commented on 23 Nov 2015有个问题 performance.timing 是只收集IOS9+ 和android 4.1+的用户吗?
chenerlang666 commented on 23 Nov 2015叼叼叼
Contributor hongru commented on 23 Nov 2015@whq731 是的,目前只作为数据补充
BelinChung commented on 23 Nov 2015typo 负责任 -> 负责人
zhouyongtao commented on 23 Nov 2015感谢分享,棒棒哒
a-jie commented on 23 Nov 2015赞
zuojj commented on 23 Nov 2015赞
tarymee commented on 23 Nov 2015赞赞赞
senyawang commented on 23 Nov 2015这个屌。 不过这种跨端的优化方案真的不是一般的公司所能做到的
Justforfei commented on 23 Nov 2015想请问下,手淘svg方面的实践
Contributor Tancy commented on 23 Nov 2015@senyawang 确实,融合naitve的能力才能发挥到极致。这个其实也是一个信号,就是我们以前只关注浏览器端的现在在移动端是远远不够的。
kevyu commented on 23 Nov 2015这个不错,希望改一下文章里的错别字。
Contributor Tancy commented on 23 Nov 2015@Justforfei 关于SVG 的我们团队用的不是特别多。不过我们整理过一份优缺点,你可以参考一下:#2
zhangxiaang commented on 23 Nov 2015赞!
jjz commented on 23 Nov 2015学习了
doudadou commented on 23 Nov 2015感谢分享
denvey commented on 23 Nov 2015SDPY协议在IOS下的支持是手淘自己实现的吗
kujian commented on 23 Nov 2015大神啊,都已经研究到这种地步了。
Contributor Tancy commented on 23 Nov 2015@denvey iOS 8.4以上已经默认支持了。手淘App是自己的网络层。
CodingPapi commented on 24 Nov 2015叼叼叼
mujiatong commented on 24 Nov 2015不错!
zhoukekestar commented on 24 Nov 2015赞!
idevz commented on 24 Nov 2015感谢分享,特别赞
wisetwo commented on 24 Nov 2015不错,学习!
idevz commented on 24 Nov 2015请问,这个图片是你们自己的监控系统吗?还是什么软件?
xiaoke88 commented on 24 Nov 2015赞
Contributor Tancy commented on 24 Nov 2015@idevz 这个是第三方监听软件,AT&T 的ARO
idevz commented on 24 Nov 2015@Tancy 非常感谢,
wewoor commented on 24 Nov 2015有发现很多不同的角度
evanhunt commented on 24 Nov 2015赞
AsiamCn commented on 24 Nov 2015 这张图片安卓性能普遍比ios差很多,是因为安卓webView性能比较差吗?为什么iOS的2G性能看上去比3G还要好?是采样数量不够吗=。= VectorHo commented on 24 Nov 2015good
WriterLuo commented on 24 Nov 2015nice
liuweifeng commented on 24 Nov 2015 xiariliaoyang commented on 24 Nov 2015 Contributor Tancy commented on 24 Nov 2015@AsiamCn 前面有个介绍android的整体情况,主要还是Android碎片化比较严重性能参差不齐。 这个地方的小于1s的占比,是各自网络段的对比,不同网络的采样率也不一样。
denvey commented on 24 Nov 2015@Tancy 有升级到http2的计划吗
Contributor Tancy commented on 24 Nov 2015@denvey 没这么快,除了服务端,还需要手淘网络层升级。其中网络层还有很多的私有技术。淘宝现在全系静态资源已经支持SPDY了(https访问)。
denvey commented on 24 Nov 2015@Tancy 看了一下caniuse,的确目前spdy是最好的选择,http2支持还要一段时间,谢谢
gwyy commented on 24 Nov 2015 zb188 commented on 24 Nov 2015感谢分享
cdll commented on 24 Nov 2015技术支持得不少啊~学习了,。
Justforfei commented on 24 Nov 2015@Tancy 谢谢~ 另外想请问下,手淘的项目已经全面使用flexbox了么?因为最近在对公司内部一个项目进行重构,关于图片方面的优化也在参考阿里的一些实践,学到了好多,
dyygtfx commented on 24 Nov 2015 edwardzhong commented on 25 Nov 2015厉害!!!
LingyuCoder commented on 25 Nov 201566666666
sphenginx commented on 25 Nov 2015学习了,感谢分享~
shaolianbo commented on 25 Nov 2015一项新的技术能让你优化1ms, 发现程序中的bug和不合理的地方,能优化1s
YuanWing commented on 27 Nov 2015真是厉害,学习一下在自己的项目中去结合运用一些,感谢感谢~
yingwu commented on 27 Nov 2015大赞, 羡慕你们的魔兔
016 commented on 27 Nov 2015点个赞,学习到不少东西。感谢。
This was referenced on 27 Nov 2015 Open有两个问题请 @Tancy 给回复下: 1)网络类型居然有 10.75% 的是 UNKNOWN ? 都比 2G 和 2G/3G 类型加起来的多,这块统计的依据是 RTT 时间,还是? 2)“最终结合SSL+SPDY+域名收敛 才发挥出真正的作用。下图是各网络下SSL 和 非SSL 的性能情况。” 的配图不太合理吧,不管 SSL 的状态是 “0”,还是 “1” 后面的协议全走 HTTP ?
yangguang1029 commented on 30 Nov 2015感觉就是能交给native层的就交给native层去做,大多数优化项都与native有关
Contributor Tancy commented on 30 Nov 2015@0x7E 1). 网络类型我们通过系统CTTelephonyNetworkInfo(iOS)和ConnectivityManger(Android)获取,对其中的(Edge,GPRS,HSDPA,HSUPA,eHRPD,WCDMA,CDMA1X,CDMAEVDORev0,CDMAEVDORevA,CDMAEVDORevB,LTE,1xRTT,IDEN,UMTS)进行了识别,其他的都是UNKNOWN.
2).这个图描述的不够严谨,是报表的展示的描述问题。SSL是1的情况就是走了HTTPS的。
Tancy closed this on 30 Nov 2015 Tancy reopened this on 30 Nov 2015 byrne-yan commented on 1 Dec 2015学到很多啊,赞!
git-patrickliu commented on 2 Dec 2015想问一下httpDNS是怎么运用到webview里面的。是Native app 给所有webview里面请求设置代理吗?谢谢:)
aszx87410 referenced this issue in TechBridgeWeekly/TechBridge-Weekly on 4 Dec 2015 Open能否详细讲一下httpDNS ?和传统dns的不一样在哪里?
git-patrickliu commented on 8 Dec 2015@steelli 传统dns受制于运营商的dns解析,容易被污染。httpDNS是通过http协议来解析DNS。具体可看这个http://www.tuicool.com/articles/7nAJBb :)
zeronexm commented on 11 Dec 2015webp格式ios目前还不支持,还是用png,jpg代替么,Android4.3支持不错
sxliusir commented on 11 Dec 2015怒赞!
Contributor Tancy commented on 14 Dec 2015@git-patrickliu Native 托管网络请求将名单内的域名替换成IP的形式访问资源。
Contributor Tancy commented on 14 Dec 2015@xiaowtz native其实已经很多年前就已经使用了webp格式。用了webp的lib库做解码。 iOS中的请求由网络层托管,将请求的webp格式的图片获取到后转码成jpg提供给webview。
budaoer commented on 15 Dec 2015你好,可以转载你的文章吗?我们会注明作者、出处。我们将转载在这里:http://www.cheng95.com/news?cid=5
SteveYangHJ commented on 25 Feb 2016目前在公司碰到一堆H5性能问题,要解决还是要向手淘学习好的解决方案。
This was referenced on 2 Apr 2016 Open@Tancy 为什么最新版本的手淘不支持 webp 格式了?
Contributor Tancy commented on 22 Apr 2016@signer 支持啊。你怎么得出不支持的?
signer commented on 22 Apr 2016测试方法: 链接1: http://image-demo-hangzhou.img-cn-hangzhou.aliyuncs.com/example.jpg 链接2: http://image-demo-hangzhou.img-cn-hangzhou.aliyuncs.com/example.jpg@100p.webp 分别用上面的链接做二维码 用手淘 iPhone 5.6.0 扫一扫, 链接1可以出来图片, 链接2直接是空白的.
signer commented on 22 Apr 2016我是手淘互动应用的 ISV, 我们的网页里用了很多 png 图片,都是转成 webp 的, 所以对这个很敏感.
Contributor Tancy commented on 22 Apr 2016@signer 是这样的,iOS中webview本身不支持webp格式的。手淘中的实现是交给图片库来完成这部分工作(获取webp格式文件转码成jpg给webview)。你测试的图片地址不在图片库的域名范围,所以才会显示空白。
signer commented on 22 Apr 2016原来如此, 这个域名范围是可配置的吗? 我可以和小二申请加入白名单吗?
Contributor Tancy commented on 22 Apr 2016@signer 不行,它不是单独的做webp解码工作。还有很多额外的工作承载。没办法将外部域名加入。
signer commented on 22 Apr 2016多谢,明白了
leleinc commented on 11 May 2016离线包的方案很不错,对性能提升具有很显著的效果。 我这有个问题:
离线包打包大小是否有限制,html css js文件都离线还是部分如何处理离线包的更新呢?增量更新还是用户重新下载整个包 Contributor Tancy commented on 11 May 2016 离线包有大小限制一般单个包的体积控制在1MB。可以所有文件都离线,这部分看业务需求。包更新手淘有一整套解决方案(消息推送)。手淘目前的更新效率可以做到第一小时95%甚至更高和一天97%甚至更高。支持增量和全量更新。针对增量的问题,我们对包也有些划分,分为基础库(相对更新频率低),和业务js包。 sansanboy commented on 16 Jun 2016如何统计访问网络是什么类型的?
dd1994 commented on 16 Jun 2016阿里云os威武...居然有 5%
Contributor Tancy commented on 16 Jun 2016@sansanboy 是通过系统方法获取到的。 iOS下CTTelephonyNetworkInfo:
Android下ConnectivityManager:
ufologist referenced this issue in f2e-journey/xueqianban on 1 Jul 2016 OpenH5是以后一个大的发展方向
0326 commented on 25 Sep 2016!很全面的总结,今年有weex的加入整体速度应该会有不小提升~
ufologist referenced this issue in f2e-journey/xueqianban on 22 Nov 2016 Open图片的大小,q值,是怎么管理的?都是使用的地方自己拼接?
Blog About