新版V8引擎的一些介绍和了解

来源:互联网 发布:面纱3.0口感数据 编辑:程序博客网 时间:2024/05/20 03:47

2017年的谷歌I/O大会召开。本文主要介绍在这次I/O大会上关于V8引擎最新的一些东西。

性能优化的多方权衡

在最开始,介绍一些关于浏览器引擎优化的基本路线,看看对浏览器引擎优化一般从哪几个方面着手。V8虽然在对javascript优化上取得很大的进步,将js的速度相比与最初提升了数十倍,采取了诸如隐藏类加PICs的技术加速属性读取,JIT技术等,但仍然存在一些问题。下面是主要几个

  • 一般来说,优化程度越好,产生机器代码的速度越快, 但会造成程序的初始化时间加长
  • 高度优化技术会造成很高的内存占用
    所以,在优化编译代码的时候需要在这几个方面进行权衡。下面这张图可以表示这中权衡过程。
    这里写图片描述

我们在上面提到过,优化程度的好坏影响着机器代码产生的快慢,优化越好,自然代码运行的速度会更快,但是会造成更长的初始化延迟,因为所有这些优化,发生在加载页面后面,浏览器首次遇到js代码的时候。所以第一个权衡就是程序启动时候的延迟和它启动后能达到的最高性能。而第二个权衡就是在JIT中,若要采取越多的优化,那么同时会占用更多的内存。所以,引擎在执行某个函数的时候需要考虑要更快的启动还是更快的运行,更低的内存还是更好的优化。

下面我们先来看看不同情况下的权衡需求。

foo(2)

现在这里有个页面,里面只包含一个foo函数,并且不知道它实际做什么。我们会发现js解释器本身的执行速度会比带有优化的js compiler速度快很多(虽然潜意识里你会认为解释器要慢的多)。因为当compiler遇到这个函数的时候,会把它转换成原生代码并且经过多次优化处理,而这一切会发生在运行之前。所以当你只需执行一次foo函数的时候,权衡策略应该这样:
这里写图片描述
这时候可能会以fast stratup为主,因为peak performance主要针对的是多次执行。
再看下面这种情况。

for(let i = 0;i<1E4;i++){    foo(i)}

这里的代码会运行foo函数10000次,我们会延长初始化时间来得到尽可能多的优化,并且转换成原生代码。而优化所用的时间可以均摊到10000次执行过程中。那么在这种情况下,将采取这种均衡策略:
这里写图片描述
我们会花费更多的初始化时间和更多的内存来大大提高多次运行时速度。当然,在桌面浏览器上完成这些优化工作是没有问题的,因为它有足够多的内存去处理多次优化。但是,当我们在低内存的安卓手机上执行这段代码的时候,很难保证客户端拥有足够的内存来进行这一系类优化,所以在这种情况下,我们会牺牲一些在PC上的优化,从而占用更低的内存。
这里写图片描述
最后,我们看下运行在服务器上的js,例如node.js。在这种情况下,我们一般认为,服务器只会启动一次(大部分情况),然后会一直保持运行并且处理请求。所以,这时候你不会过多关注它的启动花费,甚至你希望它尽可能的在初始化的时候去优化所有代码,来保证运行时的速度。所以,它的策略如下:
这里写图片描述
但是,还有一种特殊情况,那就是IOT设备。在IOT设备上,你不得不考虑内存的限制,所以需要牺牲一些优化来降低内存:
这里写图片描述

通过上面的几个例子,我们可以看到哪怕一个简单的javascript函数,都要几种不同的优化方式针对不同的环境,不同的设备。而现在的V8主要做的就是根据不同的情况,由引擎决定是偏向peak performance或者low memory,或者想要更快的启动。
所以,目前最新版的V8已经采用了一个全新的编译架构来替代过去的编译路线。下面我们通过一张图看看两个不同的编译架构。
这里写图片描述
之前的V8引擎主要由Full-codegen和Crankshaft组成。Full-codegen是成代码并且不带优化的快速生编译器,而Crankshaft则是执行效率高、优化过的代码的慢速编译器。但是在新版的V8种,这些都已经被完全替换了。
为了更好的均衡不同条件的下的优化,以及为了更好的支持webassembly,V8新加了解释器,并且用TurboFan代替过去的Crankshaft履行优化的职责。(上图中的黄色部分和Crankshaft都已经不存在了)下面我们来看看V8的里面包含的内容

TurboFan

TurboFan是一个包含优化过程的编译器。作为一个优化编译器,新的TurboFan能够生成性能更好的原生代码,并且支持优化在ES2015以及ES2016,17规范中出现的新特性,如Try,catch,finally这些现在以及能够得到最好的优化了。同时,V8也填补了过去一些个性能方面的坑。 另外TurboFan也支持WASM的优化。

Ignition Interpreter

Ignition 是用来处理一种情形的,程序的初始化需要很快,但是却有着较低的内存空间。Ignition 是一个解释器,我们在上面提到过,如果你在合适的时候去使用解释器,它的效果会好过编译器。通过Ignition 的处理,会生成可供运行的字节码,这种字节码的方式对于加速那些大型页面加载有很大的帮助。

Ignition可以与TurboFan一起工作,它会观察并发现哪些方法是经常被使用的,对于这些方法可以送到TurboFan进行优化。它俩一起就可以实现对不同的情况做出最好的优化,无论是低内存,高性能之类,并且对于node.js的支持也更完善。

Orinoco

Orinoco是新版V8种的并行垃圾回收器。在之前的V8垃圾回收器在并行处理这块并不好,而现在的Orinoco通过多线程处理,极大的提高了垃圾回收器的性能,减少在清理内存时可能对程序造成的影响。目前我只从开发者大会的介绍中了解到一些它的情况,想要深入研究的可以下载最新的源码看看。

V8的benchMark

网页性能测试从07年到现在总共经历了数个阶段。从最初的只是用一些特别的语法,诸如循环1E7次,做特定的性能测试;从12年开始,性能测试转为用编写好的静态应用测试页面,例如pdf.js之类,尽量模拟真实环境进行测试。而到现在,性能测试已经从静态测试转为动态测试。测试不再基于某一特定方面或者某一静态页面,而是通过测试真实网页行为,如逛亚马逊和淘宝,观看youtube视频,通过这样的real-world page来获取浏览器特近用户的真实性能。

所以,之前的基准测试工具Octane也已经被废弃了。目前google的基准测试都采用Speedometer,这个工具会在不久后可以到browerbench.org找到。通过这个最新的工具测试V8的性能在不同平台上都有着20%-35%的提升。

Speedometer不光测试用户浏览的真实页面,也同样支持目前流行的大多数框架应用,诸如MVC,babel,react,Angular,Vue等,并且将会支持webkit。

V8对于ES2015的优化

在之前版本的V8中,对于ES2015或者更高版本的语法实现,在初始化上都会很慢,因为引擎会花费更多的时间(相比ES5)去优化它。

所以,google通过一个名叫“6 speed”的工具完成对新语法的优化。6-speed可以去比较ES2015 版本的代码和它的transpiled version之间的差异,从而对ES2015进行优化。通过这个工具,目前最新的V8已经实现了对诸如for of,Object.assign,iteration,spread等新语法特性的优化,在性能上从最初的接近3倍的差距到现在的几乎相当。所以呢,作为一个web开发者,已经没有理由不去用新版ES中那些高级语法了更方便的完成你的工作了。

特别值得一提的:目前最热门的异步语法,async/await相比之前得到了4.5倍的提升。

关于Dev Tools

浏览器的开发者工具一直是所有开发人员依赖的重要法宝,而dev tools的升级,也意味着可以更好的帮助开发人员进行开发工作。下面将介绍一些,

  1. 在canary中可以看到一个新增的Coverage工具。这个工具可以侦测在程序执行过
    程究竟有哪些函数被使用了。比如,你在页面编写中引用了一个代码可能有几千行的库,你在调试过程中想要知道这个库中究竟有哪些代码是你需要的,通过Coverage工具,你可以很清楚的看到哪些函数被执行,而哪些是根本没有被用到过的。再进一步,这个工具可以自动帮你清除那些无用的代码,一个6000行的库,在代码清除优化后,留下了的不到1400多行。

    在大型工程中,常常会引入很多的依赖库,使用Coverage你可以快速而且清楚的知道,哪些依赖或函数或者具体代码是你需要的并且会使用的,哪些依赖的你可以删除来对你的程序进行瘦身。
    此外,新版的performance
    panel配合Coverage可以看到在Coverage使用到的函数,它们的执行过程中所耗费的时间,来帮助你更准确的去优化你的代码。

  2. 新版的V8对async的调试,进行了很大的改进,开发者现在可以很方便的对async这类语法进行调试。

WebAssembly

在最后介绍的就是这两年异常火热的WebAssembly(WASM),WASM最初起源与asm.js项目,后来几家巨头看到这个技术,觉得就是javascript的出路,因为传统的优化技术似乎对js性能的提升越来越小了。而asm.js的性能可以堪比原生代码,所以在google,微软,Mozilla等公司的支持下,WebAssembly诞生。目前,V8对WASM提供了支持。此外,还有firefox对它提供了支持,而IE Edge以及webkit的预览版也提供了支持。

WASM到目前来说,仍然相当新的技术,但已经成了几家浏览器厂商共同支持的技术,这也是第一个自提出就被几家不同浏览器所支持的技术。通过WASM,开发者可以用c,c++开发,通过Emscripten编译成web应用并且在chrome上运行。目前WASM技术也有很多成熟的例子,比如虚幻引擎制作的页面,或者一个Unity game。

总结

新版的V8在优化执行上,可以根据不同的环境,不同的设备来做出最合适的优化。同时对ES2015高级语法也提供了更好的优化,让开发者放心的使用,同时对node.js提供了更好的调试支持。最后,关于WebAssembly,WebAssembly可以进一步提升javascript或者引擎运行代码的速度,以后会有更多这方面的应用出现。