饮源 阿里巴巴技术专家
既昨日给大家介绍了过去一年里Weex业务规模不断扩大,业务复杂度不断上升,给Weex带来了哪些技术挑战,以及Weex在技术架构和设计上做了哪些升级来应对这些挑战。
今天,我们会从内核角度切入,为大家继续带来Weex技术演进之路的分享。
内核挑战
随着Weex业务规模的扩大和业务覆盖场景的丰富,Weex 不仅在性能稳定性上面临越来越大的挑战,在安全隔离方面,也遇到前所未有的风险。
性能方面:例如,去年的“双11”和今年“双11”主会场规模对比,去年整个会场的JS Bundle大小控制在250K以内,今年主会场页面平均达到500K+,业务复杂度增加了接近2倍,Weex 的加载性能跟JS bundle 的大小基本成正相关;
稳定性方面:业务场景覆盖面的提升,从原来的偏展示的场景到偏交互场景的业务,以及一些常规业务的接入;新的业务场景,必然导致新的稳定性方面的挑战,事实也如此;
富交互:引入Gcanvas、AR/VR等富交互场景,对Weex js-native的通信效率要求极高;
安全性:旧引擎的安全漏洞的问题,以及业务之间存在相互污染,无法做到安全隔离的问题;
证书问题:Yoga引擎的证书授权问题;
内核技术演进
从三个方面来阐述Weex 在内核重要方向的演进:JS引擎、Layout 引擎、WeexCore架构的演进;
JS引擎: 我们的目标是更快、更稳定、更安全、更小;其一:我们投入大量资源在JS引擎的优化上,从JS引擎的替换,由原来旧版本的V8 换成最新版本JavaScriptCore;其二:我们开创性地将JS Runtime 运行于独立的进程里,不仅保证主进程的稳定性,而且加入了智能恢复的能力;其三:重新考虑Weex 业务隔离的安全问题,开发设计了多Context 隔离的方案,保证避免业务间互相污染;其四:瘦身,包的精简;
Layout引擎:Weex项目成立以来,我们一直借用的Facebook的Yoga项目作为我们的布局引擎,但是Layout引擎对于Weex 项目又是如此重要,所以,我们今年10月份开始计划开发全新的Layout引擎开发的项目,来替换yoga引擎。第一,Layout 引擎作为核心模块,我们希望去主导演进的路线; 第二,Facebook的证书风险不能回避;所以我们决定重新开发自己的Layout 引擎,并争取做到更高性能,支持更多布局方式;
WeexCore架构:今年我们讨论最多的就是Weex 后续如何演进,在性能稳定性方面如何做的更优,在复杂业务的支持方面如何做的更好。WeexCore 首先是高性能的,用以满足更复杂场景业务开发,以及提升业务开发体验;其次是一个跨平台的内核,从DSL的跨平台到内核的跨平台。
JS引擎技术
众所周知,JS 引擎至于Weex至关重要,是Weex 最重要的一个核心模块,2017年,我们在JS 引擎的投入也是非常大:
- 2017-3月~2017-7月:对最新版本的V8和最新版本的JavaScriptCore 做来全面的profile,让profile数据告诉我们去选择哪个引擎作为Weex新一代的JS 引擎。经过4个月的努力,终于将最新版本的JavaScriptCore 在手机淘宝正式版本上线,同时Weex也是第一个将JavaScriptCore引擎(javascriptcore引擎apple维护的,很少在android平台商业化过)集成到手机淘宝这样体量的App中,中间遇到的兼容性的问题也是我们最大的挑战。最终性能提升还是比较明显的,手淘上Weex整体业务首屏加载时间提高了40%+,并全面支持ES6特性;
- 2017-7月~2017-10月:新版本的JavaScriptCore 上线以后,Weex的稳定性native crash 占比5%左右,按照手淘的稳定性要求(<1%)还是有比较大的差距,这个将是我们2017年双十一前最大的挑战。当时Weex稳定性小组的同学出于焦虑中,随着双十一临近,不断有新Weex 业务上线,伴随着冒出一些的兼容性的问题出来,始终看不到收敛的趋势。一方面,我们正向地去解决这些适配的问题,另一方面,我们也讨论如何彻底地解决JS引擎的稳定性的问题;后来,我们想到将JS 引擎独立运行到单独的进程里去,这个方案带来最大的好处,就是Weex 业务的crash 不会影响主程序的稳定性;这个方案也成了双十一Weex稳定性保障的救命稻草。最终这个方案在10月份前正式上线,效果非常明显,Weex 引起的native crash占比一下子从5%下降到0.5%左右。
- 2017~11月~至今:双十一之后,JS 引擎项目主要在做两个事情,一个Weex安全隔离方案,另一个是包精简优化方案;Weex安全隔离方案主要解决页面隔离的问题,双十一当天也遇到一个非常严重的全局污染的案例,某个业务不小心污染了全局对象,导致所有的Rax的页面出现白屏的问题;针对这些案例,我们重新设计了Weex 安全隔离的方案,目前安全隔离方案已经内部灰度中,预计2月份正式社区发布;包精简优化方案:主要解决Weex sdk集成了最新版本的JavaScriptCore以后,包大小增大一倍的问题(4.2M左右),包的增大直接增大了App接入的门槛,特别是对包大小非常敏感的App。目前同步一下信息:精简优化方案目前也基本开发完毕,预计可以减少到2.6M左右,预计也是2月份上线;
独立进程化
问题
- 同一个进程中,与主App存在资源竞争,尤其是内存问题比较突出,JavaScriptCore虽然执行性能提升了,但对内存的消耗也同时增大不少,所以替换成JSC以后,Weex的内存问题导致Crash也明显上升;
- 独立进程的方案本身比较Hack,再加上Android生态的碎片化,开发过程中也遇到很多适配问题,比如在某些机型上独立进程拉不起来,导致业务渲染失败;
- JavaScriptCoe引擎本身对android平台适配比较差,没有比较大体量的App在线上应用过;
优势
- 进程独立以后,完全和主App的进程隔离,避免了进程资源竞争导致crash的问题,Weex的crash也不会引起主进程的crash;
- Weex 原有的三个线程架构,JS 线程任务被并行成两个,JS独立的进程和原来JS线程,整体增强了JS任务执行的并发性,抵消了方案本身的IPC通信的性能损耗;
- 独立进程后,我们加入了自修复的能力,增强了JS Runtime进程的自动重置功能,解决JS Runtime 异常后的无法自动恢复的问题,极大地保障业务的稳定性;
Weex 原有的设计,所有Weex页面包括JSFrameWork 都是运行在同一个JS Context里,并在JS层面,对全局的JS 变量做了freeze操作,防止被其他业务页面污染。这个设计主要还是出于高性能和安全性的综合考量。
2017年双十一出现的全局污染的问题,让我们重新思考Weex Context的安全隔离的方案,安全稳定高于一切。经过新的讨论后,我们决定针对每个Weex页面都创建一个JS Context 作为独立的运行环境,页面依赖的全局对象由Global Contex统一生层并传递给每个页面的Contex;传输的过程,我们做了两个非常重要的操作:
1)对传输的对象做freeze操作;
2)在javaScript引擎层面,通过native的SetPrototype接口切断原型链的关系;这样就彻底解决了页面间互相污染的问题。该方案预计2月份正式上线。
Layout 引擎
全新的Layout引擎参考了 Google的FlexLayout的算法流程,重新实现了Weex的 Flex布局,目前性能和功能方面基本和yoga保持一致,后续会做一些性能优化。至于未来如何演进,团队同学讨论几个关键的步骤:
-
自主开发全新的高性能的跨平台Layout引擎,统一由C++实现,IOS/android 两端复用同一套代码;
-
扩展更多的布局方式,比如Gird布局、Absolute布局等
-
编译器或服务端做预布局,提升端测的布局效率等;
该方案预计2月份正式上线。
WeexCore 架构升级
Weex 作为一个跨平台的开发框架,在Android/ IOS/HTML 三端实现跨平台一致性非常重要。目前Weex 核心渲染流程分平台实现,不仅多人维护导致不可避免的逻辑实现差异,而且对于后续新平台扩展成本也非常高(核心渲染流程需要重新实现)。因此,想到抽象统一Weex 核心解析渲染流程,通过C + + 语言实现,实现 ios、android 平台核心逻辑统一,不仅可以增强平台间的一致性,降低维护成本,以及扩展平台的成本。通过C+ +代码执行效率要高于JAVA,同时还可提高Android端的代码执行性能。
- 提供标准的Weex Dom API Layer,简化DSL的接入成本,将大部分JSFramework native化;
- 抽象Weex平台无关的、核心的处理逻辑,android和IOS的porting层尽量做薄,一方面提高代码的复用率,另一方面降低新平台的扩展成本;
- 架构设计上的高可用,通用的模块可插拔,例如JS engine 模块和Layout engine模块能低成本地切换;
- 核心技术模块比如JS engine 等能标准化输出,服务更多的业务场景;
原文发布时间为:2018-01-26
本文作者:饮源