作者|手淘用户体验提升项目组

出品|阿里巴巴新零售淘系技术部

历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)我们重点介绍了手淘在性能优化中的一些实践和思路,主要集中在原生的代码的优化,这次,我们将继续分享在手淘容器化页面如 H5 及 Weex 相关的优化实践。

Weex 化的店铺性能优化

▐  背景

店铺业务做为商家运营、营销的主阵地,是动态化方案激进的跟进者之一。2015年上线 Weapp 技术,就是在一码多端上的尝试。2017年,WeappPlus 的项目斐然崛起也和店铺有着千丝万缕的联系。

没看错,就是 Weex 的第一个项目名。之后 Weex 如一阵飓风般刮过集团各大业务,或整体、或单页、或卡片的应用场景层出不穷。店铺作为第一批上线 Weex 的业务,承担积极的推动作用,甚至一度把客户端给做没了,客户端仅保留了店铺路由的逻辑。在页面渲染和呈现上,全业务、全页面都由 Weex 来承载。

但是众所周知,Weex 技术在带来种种优点的同时,也有一个无法避免的短板。页面进入速度会变慢(相对于纯客户端页面而言),特别是店铺这种既需要复杂交互,同时还有三方 ISV 开放能力,单个页面的 js 超过 500K 的复杂业务场景。

在结构上,店铺的分为 框架 - 子页 两部分:

框架包含店铺名,心钻冠等级,顶部 tab 条,底部 tabbar 导航的能力。子页就是各个 tab 切换后的中间区域。首页就是屏幕中央的主要业务区域,可以通过 tab 完成多个页面间的切换。

框架 和 子页,通过 embed 标签完成嵌套关系。

同时为了让用户获得更大的浏览区域,引入了 Nested-Scroll, BindingX 等能力实现嵌套滚动,底色渐变等能力。

最后店铺外投的 URL 形式众多,需要有能力支持各式各样的入口地址。

综上,整个进店流程从链路上说可以分为三个阶段:路由,框架,首页。


接下来,将从设计、分析、实现、上线等角度阐述整个优化工作的具体实现。

希望能够帮助读者在优化自身业务时,有更多的方法。

▐  开工

★  优化开始的第一件事是什么?

对,就是找把尺子。

先确定好衡量的环境 和 数据口径,做到手中有尺,心中不慌。

只有明确了标准,才能使工作的价值 更清晰、更准确、更容易 得被衡量。

特别当兴冲冲得找老板汇报已经完成目标,结果一测发现还差一大截时,更能体会这条 tips 的重要。

★  第二件 备好工具

直接代码打性能日志

(最简单也是最好用)

有个小建议,同时输出时间戳 和 时间差。同时按一条主要的关键路径,把先后的日志按顺序串起来。SystemClock.uptimeMillis() 不推荐使用,请使用 System.currentTimeMillis() 。

这样有个好处,当有多个系统交互,比如 前端 客户端java 客户端c++ 就在一条时间基线上,串起来看清晰很多。

Systrace + TraceView + top + Charles

Systrace: 目标是跑满 cpu,这个在项目优化初期做一下,对整个流程有个宏观感觉。项目冲刺阶段做一次,重点突破。

TraceView: 可多看看,找耗时方法很有效。

top: 在遇到分析瓶颈的时候,不妨试试,往往能看出一些线索,比如 USER CPU 占用偏高,重点分析是否和多线程场景 和 检查 c++ 任务调度。


Charles:在定位到底是 网络慢 还是 处理慢 的问题上,往往一针见血。

所有工具都是手段,最重要的还是对 流程的理解 和 业务的熟悉。

adb shell input tap

input tap 这个简单的特性,往往能化腐朽为神奇,减轻偶现问题的修复验证工作。

▐  技术选型

回忆下前面提到的店铺渲染三大阶段:整个优化工作都是围绕这三个阶段展开。这里进一步对三步进行细化,见下图。

★  框架 - 子页 并行渲染

在上述店铺三阶段中,可以发现 店铺框架 和 店铺首页,作为两个独立 WXSDKInstance,在整体流程中耗时占比较大。很朴素地就考虑到能不能将这两步并行起来。

优化前由前端代码通过 embed 标签,直接就能确定了「子页」和「框架」嵌套关系 和 嵌套位置。流程相对简单。

在引入并行渲染的优化后,事情变复杂。由客户端并行承载两个页面的绘制工作,再选择合适时机,把两个页面组合起来。

从流程上来,「框架」和「子页」的 weex 渲染任务会并行进行。并且同时取消了「子页」的 loading,在用户交互感知上少了一个等待的过程。体感上提示很明显。

★  数据请求托管

经过分析,传统方式下,一次店铺打开,共有五次数据请求。虽然前端可以利用 Promise 技术做并发,但是依然存在等待数据的状态。

针对上述五次请求,具体场景不同有不同的优化策略,其基本方向还是数据请求合并,并发请求,异步请求。

过程中的注意点:

1. 最优先考虑的还是数据合并,将多个数据请求合并成一个,最简单且效果最好。

2. 并行数据请求,复用的是 weex 实例创建的时间,越早请求,效果越好。

3. 异步请求的场景,远程数据获取 和 前端数据拉取 的先后关系不定,要注意数据缓存的设计。

4. 对于所有处理数据的weex 模块,所有方法都不需要主线程执行。

★  JS-Bundle 提前准备

总所周知,优化 JS-Bundle 的加载速度,是提升 weex 业务体验最有效和最直接的抓手。

针对绝大多数 weex 场景,通过手淘现有Cache 技术完成 JS-Bundle 的客户端侧存储,已经可以很好地支持业务。但对于店铺这个 pv 亿计体量的业务还略显不足。主要体现在:

  • 到达率无法准确把控

  • 更新时间较久

  • 磁盘加载稍慢。

针对上述几点改进空间,并且结合业务特点定制了 JS-Bundle 端侧存储能力。主要特点:

1. 除首次纯新安装场景,其余情况总是优先返回本地缓存的 JS-Bundle。同时根据两次访问的时间差,判断是否要刷新本地缓存。且遵循 http 的 cache-control 策略。

2. 客户端侧底层存储使用统一存储,在手淘打开后的首次访问时,读数据很慢,甚至在高端机上比走网络还慢。所以选取合适的时机做预热。

3. 内存级缓存。内部使用 SoftReference 包裹数据体,防止 OOM。同时在 切后台 和 接到低内存警告 的时候,触发对象释放机制。

在引入 JS-Bundle 提前准备后,用户最直观的感受就是整页白屏 loading 等待的时间大幅缩短,甚至页面转场完成时,首页就已经渲染完毕,避免了用户视觉上的空窗期。

★  上下游优化

再提几个比较容易忽略的优化点。

Weex Module 的调用

每次 module 调用虽然耗时很短,但是因为每次都要等待 WXJSBridge 线程空闲,并且获取到 cpu 时间片才能执行。所以常常会出现方法调用耗时 10ms,等待耗时 300ms 的现象。这点主要从前端优化。

一方面尽量减少 module 调用,特别是关系到主链路的渲染流程中的 module 调用。

另一方面,将不重要的 module 调用延后。例如店铺就将部分 ut 埋点逻辑,做了延后处理。

流程上看,通过减少 JS-bridge 的任务调用,减少线程切换时间,从而减少 weex 渲染 view 的上屏时间。最终减少用户可流畅交互时间。

图片预加载

针对图文较多的业务,在客户端获取到数据接口后,直接利用图片库的预请求能力,做图片的加载。

硬件加速

部分手机厂商向公司开发了 API,允许在特定场景下调升 CPU 频率,从而实现加速的效果。

最后也是最简单的一点

减少 JS-Bundle 的文本大小,是最直观的提效做法。

优化业务的前端代码,去掉过期的逻辑,去除无用判断,去掉冗余的依赖。

店铺业务大约减少了 80K+ 的 js,获得了大约 40ms- 的性能提升。

综上:所有优化点上线后。整个流程链路以下图流程经行。

通过店铺性能调试工具可以实时验证观察各阶段的渲染效果。

Web 前端性能优化实践

前端 Web 页面的性能给大多数人的印象可能还停留在几年前的加载白屏、滑动体验差等,但是到了现在这个时间节点,必须停下来重新思考下现有的业务发展、技术开发方式等,最终我们觉得有理由并且有能力从全链路的角度来看前端 Web 页面性能,最终突破这一刻板印象。

▐  优化思路

在进行优化前,梳理了几个原则:

1.明确目标:整体页面端内首屏时间 1.2s,端外首屏时间 3s,低端机首屏时间小于 2s,可交互时间小于 2.5s,可流畅交互时间小于 3s。性能优化无止尽,定好目标才能有的放矢。

2.梳理端到端系统化每个环节:梳理宏观的每个环节,再具体分析到细节点。

3.数据驱动性能优化:线上收集各个环节的性能数据,便于分析。

4.投入产出比 ROI: 不要迷失在性能优化中,思考技术对于业务的价值。

★  各环节耗时分布

这张表统计了从点击开始到渲染完成各个环节的耗时分布,各个最低数值代表理论可行值,最大值代表线上真实数据耗时,因此可以清楚的知道哪个环节现阶段是最差的,然后进行针对性的分析和优化。

最终会不断的调整这张表的数值分布,然后看哪个阶段还能继续优化,形成优化并数值调整 -> 线上验证 -> 再优化调整的正向循环。

▐  渲染方案

目前基于线上数据验证以及线下对比,如果一个页面资源(包括文档 HTML、js 资源)都是走缓存的形式,整体页面的性能、体验会比较好,对文档、资源的缓存非常关键。因此整体的渲染方案会最大限度的利用缓存,设计如下:

1.袋鼠服务:面向前端的数据接口合并服务,模块直接取数据渲染,保证了页面渲染的一致性

2.统一渲染页

  • 数据驱动页面渲染,所有页面的核心逻辑一致

  • 保证模块渲染与页面的分离,确保统一渲染页被稳定缓存

3.页面渲染策略:区别首屏/非首屏渲染,保证首屏能快速渲染

4.模块缓存池:解决所有页面模块缓存问题

▐  优化系列

基于性能优化的手段,目前我们可以主要分为以下三种:

★  加载

对于一张页面的加载,我们要做到 4 个 1:

  • 一个共享文档

  • 一个首屏关键 js

  • 一个首屏业务 combo 资源

  • 一个全局共享缓存池

主要罗列了以下几个优化手段:

1.按需加载:某些特别大的 js 资源可以按需加载,比如安全脚本大小会有 500K+

2.分环境加载:由于目前端上 es6 环境支持的程度已经较好,因此可以在绝大多数场景去除 babel-polyfill 的依赖

3.资源缓存:端上 combo 资源按版本拆分缓存

资源缓存

1.端上共享缓存池,缓存 combo 后的资源到内存以及缓存解 combo 后的缓存到内存/磁盘,这样在二次访问时达到重复利用的目的。

2.优化资源传递消耗,内核之间只需 Stream 流形式传递,避免了类型如 byte -> String -> byteStream 之间的类型转化消耗。

优势:

1.无需推送 ZCache,共享单个级别的资源

2.性能好:缓存 20-100ms vs网络请求 200-300ms+

3.优于 httpcache,可以命中更多的 combo 组合

劣势:

1.会占用一定的内存来换取资源读取上的优势

★  渲染

对于渲染,我们要做到首屏尽可能快的渲染完成,主要罗列了以下几个优化手段:

1.首屏/非首屏渲染,更细粒度的按行懒加载:对于一整张页面,我们希望能优先渲染首屏,可以尽快的呈现内容让用户看到。有时候首屏的内容也会非常长,还可以做到按行级别的控制懒加载渲染。

2.js bridge 通道优化:端内需要有较多的与 native api 交互,通信效率也至关重要。

js bridge 通道优化

核心:解决JS引擎与内核 Java 层同步 IPC 通信阻塞问题

优化前

使用 prompt 方法进行 jsbridge 通信


1.JS 引擎与内核 java 层同步IPC通信,阻塞 Render 线程,通信耗时:中/低端机100-200毫秒,导致延长渲染时间

2.引发内存泄漏问题

3.引起渲染引擎重排版,平均耗时 100ms 左右

优化后

使用 onConsoleMessage 方法进行 jsbridge 通信

1.JS 引擎与内核 java 层异步IPC通信,不阻塞 Render 线程

2.不引起渲染引擎重排版

★  数据

数据 Prefetch & 时机提前

核心:解决数据/渲染并行执行,尽可能的减少数据请求时间

1.利用了容器的初始化时间,进行并行数据请求,从而节省数据的请求时间

2.进一步提前数据请求时间点到点击
最终的节省时间 = 容器路由时间(找哪个容器渲染) + 容器启动时间 + 容器初始化时间 + 页面框架渲染时间

中间过程优化

核心:解决子线程与 UI 线程的阻塞问题,以及中间环节没必要的类型转换

优化前

优化后

最后

从宏观到微观。性能优化之初一定要有宏观视角,对整个框架的运行情况,要有做到心里有数,对问题进行全面分析,然后再对瓶颈进行拆解,拆解后的子任务也不能孤立去看,一定要放在系统内,综合选择最优方法。

建立长期管控机制。性能优化成本也非常昂贵,性能优化在某种程度上,与其说是技术人员秀肌肉,不如说是还债,技术债(当然,真正有技术挑战在一些特定条件下做极致优化的情况不在此列)。从最初的技术方案设计,业务压力下充忙上线,线性的功能堆积,对现有架构设计的妥协等多种原因导致了性能问题的。如果在上线之初就能考虑到对性能的影响,好好设计方案,这时的成本是最低的。然而,一切依赖人的行为的机制都是不靠谱的,老虎也有打盹儿时。要减少运动式的做性能优化,需要建立一个依赖于客观数据长效的监控机制,这也是我们正在探索的方向。

路漫漫其修远兮,吾将上下而求索。

今日话题

还想了解什么内容?下方评论区留言~

你来说,我安排!

推荐阅读

历时1年,上百万行代码!首次揭秘手淘全链路性能优化(上)

别催更啦!手淘全链路性能优化下篇--容器极速之路相关推荐

  1. 阿里巴巴淘宝全链路性能优化(上)

    作者|手淘用户体验提升项目组 出品|阿里巴巴新零售淘系技术部 导读:自阿里在11年提出 All in 无线之后,手淘慢慢成长为承载业务最多,体量巨大的航母级移动端应用.与之相应的,手淘离轻量,快速,敏 ...

  2. 手淘双十一性能优化项目揭秘

    亿万用户都会在双十一这一天打开手机淘宝,高兴地在会场页面不断浏览,面对琳琅满目的商品图片,抢着添加购物车,下单付款.为了让用户更顺畅更方便地实现这一切,做到"如丝般顺滑",双十一前 ...

  3. 手机淘宝 521 性能优化项目揭秘

    http://www.infoq.com/cn/articles/mobile-taobao-521-performance-optimization-project 又是一年双十一,亿万用户都会在这 ...

  4. 天猫11.11:手机淘宝 521 性能优化项目揭秘

    又是一年双十一,亿万用户都会在这一天打开手机淘宝,高兴地在会场页面不断浏览,面对琳琅满目的商品图片,抢着添加购物车,下单付款.为了让用户 更顺畅更方便地实现这一切,做到"如丝般顺滑" ...

  5. 精读《手写 SQL 编译器 - 性能优化之缓存》

    1 引言 重回 "手写 SQL 编辑器" 系列.这次介绍如何利用缓存优化编译器执行性能. 可以利用 Frist 集 与 Match 节点缓存 这两种方式优化. 本文会用到一些图做解 ...

  6. 最全前端性能优化总结

    最全前端性能优化总结 前端性能优化分两部分 一.加载性能优化 1.减少请求次数 为什么减少请求次数? 减少请求次数方式 2.减少资源大小 减少资源大小方式 3.网络优化 其他 二.渲染性能优化 **浏 ...

  7. 淘宝网性能优化之借鉴——webp及Bigpipe

    前言 说到性能优化,我博客前面文章讲了不少,其实性能优化做的好坏,直接体现前端开发人员的水平.因此,很多面试中基本上都会提及这一点.今天主要借鉴淘宝网性能优化方式之一webp及Bigpipe 进行简单 ...

  8. 高德全链路压测——语料智能化演进之路

    背景 高德地图作为日活过亿的国民级出行生活服务平台,承载着海量用户服务的是后台的超大规模集群.从用户角度,如果出问题,影响会很大.3机房异地部署造成线上环境复杂,链路复杂.在这样的条件下,如何避免因故 ...

  9. 史上最全Android性能优化方案解析

    Android中的性能优分为以下几个方面: 布局优化 网络优化 安装包优化 内存优化 卡顿优化 启动优化 -- 一.布局优化 布局优化的本质就是减少View的层级.常见的布局优化方案如下: 在Line ...

  10. spark 算子使用类变量_自己工作中超全spark性能优化总结

    来源:https://zhuanlan.zhihu.com/ p/108454557 作者:一块小蛋糕 编辑:深度传送门 Spark是大数据分析的利器,在工作中用到spark的地方也比较多,这篇总结是 ...

最新文章

  1. 第七届蓝桥杯大赛个人赛省赛(软件类)B组真题
  2. 不能使用 '';文件已在使用中。
  3. java反射创建对象_java8反射创建对象
  4. switch 根据键盘录入成绩 显示分数及判断等级(第一次)
  5. CRM_UPLOAD_BW
  6. 刘慈欣推荐!这本“疯狂的书”预言9年后人类将永生?
  7. SqlMap异常的处理
  8. createplayer 多次调用 位置错误_Programming in Lualua学习第6期 Lua编译执行与错误
  9. vim使用系列之二——总结一下自己常用的VIM操作
  10. arduino 中断 串口_【Arduino教程】第一讲:Arduino是什么?
  11. java线程死锁_Java线程死锁实例及解决方法
  12. 大学计算机基础教程大纲
  13. win7快捷关闭计算机,win7关机快捷键和重启快捷键是什么?
  14. k8s 集群全部更换机器 IP
  15. C语言客房管理系统课程设计
  16. 微型计算机课程设计电子密码锁,《微机原理及应用》课程设计基于74LS112的电子密码锁设计报告初版...
  17. 哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度
  18. elasticsearch-7.17.4 基础班升级到白金版本
  19. 少儿编程培训 python
  20. 使用 adb logcat 显示 Android 日志

热门文章

  1. php根据身份证号码确定地区(省份)地址
  2. linux中vi后如何退出命令,linux用VI编辑后保存退出命令是什么啊?
  3. Inter core i7处理器中(x86架构)驱动开发:关于APCI Hardware ID的描述
  4. SpringBoot2.x整合Redis数据库
  5. 修复windows系统快捷方式图标变成白色的问题
  6. opencv学习(二十四)之腐蚀与膨胀
  7. 图片标注工具Labelme使用
  8. win10屏幕保护色设置
  9. 我去,还有这种网站!
  10. 【工具分享】画流程图工具Gliffy Diagrams