简介:在大前端时代,性能问题已经逐渐成为前端火热的话题,因为随着项目的逐步变大,页面动画和交互的复杂度逐渐提高,性能问题也逐步体现出来。为了提高用户的体验,减少加载时间,工程师们想尽一切办法去优化细节。在这 ...
在大前端时代,性能问题已经逐渐成为前端火热的话题,因为随着项目的逐步变大,页面动画和交互的复杂度逐渐提高,性能问题也逐步体现出来。为了提高用户的体验,减少加载时间,工程师们想尽一切办法去优化细节。在这一篇文章中我们将来学习如何让 V8引擎 优化我们的代码,之后将会学习性能优化剩余的琐碎点,因为性能优化这个领域所涉及的内容都很碎片化。在学习如何性能优化之前,我们先来了解下如何测试性能问题,毕竟是先有问题才会去想着该如何改进。测试性能工具Chrome 已经提供了一个大而全的性能测试工具 AuditsJS 性能优化JS 是编译型还是解释型语言其实并不固定。首先 JS 需要有引擎才能运行起来,无论是浏览器还是在 Node 中,这是解释型语言的特性。但是在 V8 引擎下,又引入了 TurboFan 编译器,他会在特定的情况下进行优化,将代码编译成执行效率更高的 Machine Code,当然这个编译器并不是 JS 必须需要的,只是为了提高代码执行性能,所以总的来说 JS 更偏向于解释型语言。那么这一小节的内容主要会针对于 Chrome 的 V8 引擎来讲解。在这一过程中,JS 代码首先会解析为抽象语法树(AST),然后会通过解释器或者编译器转化为 Bytecode 或者 Machine Code2016 年手机解析 JS 代码的速度 这里需要注意一点,对于函数来说,应该尽可能避免声明嵌套函数(类也是函数),因为这样会造成函数的重复解析。function test1() { // 会被重复解析 function test2() {}}然后 Ignition 负责将 AST 转化为 Bytecode,TurboFan 负责编译出优化后的 Machine Code,并且 Machine Code 在执行效率上优于 Bytecode function test(x) { return x + x}test(1)test(2)test(3)test(4)对于以上代码来说,如果一个函数被多次调用并且参数一直传入 number 类型,那么 V8 就会认为该段代码可以编译为 Machine Code,因为你固定了类型,不需要再执行很多判断逻辑了。但是如果一旦我们传入的参数类型改变,那么 Machine Code 就会被 DeOptimized 为 Bytecode,这样就有性能上的一个损耗了。所以如果我们希望代码能多的编译为 Machine Code 并且 DeOptimized 的次数减少,就应该尽可能保证传入的类型一致。那么你可能会有一个疑问,到底优化前后有多少的提升呢,接下来我们就来实践测试一下到底有多少的提升。 优化与不优化代码之间的巨大差距 从上图中我们可以发现,优化过的代码执行时间只需要 9ms,但是不优化过的代码执行时间却是前者的二十倍,已经接近 200ms 了。在这个案例中,我相信大家已经看到了 V8 的性能优化到底有多强,只需要我们符合一定的规则书写代码,引擎底层就能帮助我们自动优化代码。另外,编译器还有个骚操作 Lazy-Compile,当函数没有被执行的时候,会对函数进行一次预解析,直到代码被执行以后才会被解析编译。对于上述代码来说,test 函数需要被预解析一次,然后在调用的时候再被解析编译。但是对于这种函数马上就被调用的情况来说,预解析这个过程其实是多余的,那么有什么办法能够让代码不被预解析呢?其实很简单,我们只需要给函数套上括号就可以了(function test(obj) { return x + x})但是不可能我们为了性能优化,给所有的函数都去套上括号,并且也不是所有函数都需要这样做。我们可以通过 optimize-js 实现这个功能,这个库会分析一些函数的使用情况,然后给需要的函数添加括号,当然这个库很久没人维护了,如果需要使用的话,还是需要测试过相关内容的。 小结总结一下这一篇文章的主要知识点:
|