本文转载自内部同事分享pennyli(李鹏)
发表时间 2022年12月14日
背景
目前QQ浏览器(下简称QB)使用Hippy的业务超过100个,基本上95%的核心业务都是使用Hippy作为首要技术栈来开发。但是跟Native相比较而言,Hippy是使用JS引擎进行异步渲染,在用户从点击到打开首屏可交互过程中会有一定的耗时,影响用户体验。如何优化这段耗时,尽量对齐Native体验,想必是每个团队需要思考优化的事情。
通过分析Hippy执行流程,找到耗时瓶颈,对比业界JS引擎方案,选择Hermes引擎,将JS离线生成Bytecode,利用引擎直接加载Bytecode的能力,在业务无需修改一行代码的前提下,让Hippy的包加载速度提高80%,首帧耗时优化50%起。
Hippy业务耗时分析
Hippy整个启动流程,依赖JS线程的执行,我们其实可以将整个过程抽象看成一个串行的操作,以QB冷启动首页Feed流,结合线上数据性能监控可以看到如下阶段耗时:
注:TTI = Time To Interact,意思是从业务创建到业务可交互所花费的时间,因为衡量业务可交互比较复杂,各个业务对可交互的定义不一样,所以这里以首帧上屏为准来衡量;
通过打点分析得到,用户从打开业务创建RootView开始,到最终首帧上屏总共耗时1488毫秒,其中主要在Module初始化、创建HippyCore(bootstrap.js以及common包执行耗时)、业务包执行耗时上;其中加载执行业务包耗时1303毫秒,占整体TTI的87%。
如果我们能够优化加载执行业务包的耗时,那么我们就可以极大的降低TTI。在iOS上Hippy使用的是系统提供的JavascriptCore引擎来运行JS代码,所以我们要分析一下JSC的执行过程。
JavascriptCore执行流程分析
具体流程:
1. 词法分析,输出tokens;
2. 语法分析,生产AST(抽象语法树);
3. 从AST生成字节码;
4. 通过Low Level解释器执行字节码;
5. 使用JIT加速解释执行机器码;(带JIT的版本)
注:JSC分带JIT与不带JIT的版本,带JIT的版本目前只有苹果自家的Safari能够使用,因为安全原因,公开的JavascriptCore实际是不带JIT的版本。下面讨论的也是指不带JIT的JSC版本。
整个流程,在JS代码被解释执行前,绝大部分时间消耗是在字节码生成上,如果能将Bytecode生成前置,缓存起来,每次执行JS的时候,直接取缓存的Bytecode,那将会极大降低耗时,但是很可惜的是,JavascriptCore是属于系统库,并没有提供这个能力,另外我们也没有办法对其进行修改。我们可以考虑选择其他支持Bytecode的引擎替换掉JSC。
可选引擎对比
除了JSC,常见的开源引擎包括V8、QuickJS、Hermes。
JS引擎 | 是否支持Bytecode | SDK大小 | 是否开源 | 作者 |
---|---|---|---|---|
JavascriptCore |
|