现在用户手机性能,浏览器性能,网络性能,越来越好,后端逻辑逐渐向前端转移,前端渲染变得越来越普遍。前端渲染主要依赖JS去完成核心逻辑,JS正变得越来越重要。而JS文件是以源码的形式传输,可以在Chrome Devtools上轻易地被修改和调试。我们一般不希望核心业务逻辑轻易的被别人了解,往往会通过代码混淆的方式去进行保护。
那么,代码混淆对JS性能是否有影响呢?我们下面讨论一个真实的案例,看看混淆如何让JS性能变差100倍,并详细介绍如何去跟进和处理类似问题。
通常JS混淆有两种方式,一种是正则替换,强度比较弱,很容易被破解;另外一种是修改抽象语法树,比较难破解。
一些比较重要的JS文件,一般会使用修改抽象语法树的方式去进行混淆保护。相关的原理请参考知乎上的文章:前端如何给 JavaScript 加密
一般来说,JS混淆会引入多余代码,修改原来的抽象语法树,可能会引入性能问题,但性能影响一般非常小。
但是,也有异常的情况,我们在一个业务上发现它的isdsp_securitydata_send.js执行非常耗时,竟然达到惊人的1.6秒。Trace信息如下,
而使用它未混淆的源码去执行时,发现在15毫秒就执行完了。这是一个非常明显的混淆引入性能问题的案例。
大部分问题,在找到根本原因之后,我们都会觉得非常简单,也很容易解决。而分析问题原因的过程和方法则更加重要,我们下面分享一些通用的分析问题的方法。
(1)确认性能问题
一般来说,确认一个JS执行是否存在性能问题,使用Chrome Trace还是比较方便的。我们下面先说说怎么看Trace信息。
上图中,
v8.run 对应内核的V8ScriptRunner::runCompiledScript, 代表blink端的JS的执行时间,即JS执行的实际耗时。
V8.Execute 代表v8内部的JS执行时间,与v8.run代表的意义一样,耗时也相近。
颜色与V8.ParseLazy一样的部分,代表JS编译耗时,从上图可以看到,编译耗时占了绝大部分。
注:上图仅仅为了展示Trace中V8相关的含义,不是我们要讨论的JS耗时问题。
从上图可以看到,v8.run下面几乎没有蓝色的片段,即几乎没有编译耗时,基本上都是JS代码执行的耗时。
这样我们可以判断,abc.js 执行的耗时达到了惊人的1.6秒,而这个JS的逻辑非常简单,它很有可能是存在严重性能问题的。
注:上图是abc.js在真实环境执行消耗的时间。
(2)分析问题原因
在上面我们已经定位到abc.js的执行耗时存在较大问题,那么可以怎么去定位问题的准确原因呢?
我们先将问题简化,把这个JS抽取出来单独去执行,比如,使用下面示例代码:
|
从上面Trace可以看到,里面一些JS函数的执行非常耗时,每个耗时都有几百毫秒。
但这个外联的JS是无法定位到代码行的,我们可以将外联JS文件的内容直接拷贝到上述