BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

在V8引擎中实现后台编译所需应对的挑战

| 作者 Abel Avram 关注 7 他的粉丝 ,译者 李彬 关注 1 他的粉丝 发布于 2014年2月19日. 估计阅读时间: 7 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

 

对于最近Chrome V8 JavaScript引擎中引入的后台编译,这篇文章探讨了其中的一些细节。

在Google浏览器Chrome的最新版本(Beta v.33)中, JavaScript V8引擎方面具有一项重要的变化:引入了使用后台线程进行优化编译处理的能力,从而让主线程能够继续对用户保持响应并获得性能提升。据从事此工作的Google工程师Yang Guo透露,V8将完成两种类型的编译

为了减少在编译方面消耗的整体时间,V8将JavaScript函数的编译推迟,直到它们首次执行前才会进行此工作。这一编译阶段非常迅速,但是并不以优化代码为重点,而是聚焦于快速完成编译。在V8中,频繁运行的代码片段将得到第二次编译——由专用的优化编译器(Crankshaft)完成。在第二遍编译中,使用了许多高级优化技术,这意味着第二遍编译将比第一遍消耗更多的时间,但是其产出的代码运行起来更快。

Guo介绍的,在使用Nexus5运行Octane 2.0基准测试套件中的Mandreel测试时,我们可以看到,通过由独立线程负责优化编译,应用不仅仅更加具有响应性,而且运行速度提高了27%。

InfoQ对Chrome V.33进行了一些测试,记录了分别使用(--js-flags="--concurrent-recompilation")或禁止(--js-flags="--no-concurrent-recompilation")并行重编译时的运行结果。对于Octane 2.0基准测试,我们观测到了以下性能提升(对连续5次测试的结果进行平均,且每次运行时都重新启动了浏览器):

测试

提升

Octane 2.0 (全部17项测试)

7.12%

Mandreel

18%

Box2DWeb

32%

zlib

11%

从上表可以看到,对于Octane基准测试套件整体的测试来说,性能提升了7%升;而在2D和3D引擎方面,提升则更为显著。

以确保我们知道他并不是为Google说好话(当时他尚未加入此团队),我们询问Guo,为何在2010年12月发布Crankshaft时没有引入优化编译。Guo表示,最新版本中增加的这些改进,都是源自实际的需求:

在设计Crankshaft的时候,延迟并不是很大的问题。考虑到当时JavaScript代码的大小,编译时间尚未成为显著的问题,因此低延迟既不算是问题,也不是CrankShaft的设计目标。在我看来,在那个时候引入并发,将令刚刚起步的优化编译器的设计,变得毫无必要的复杂;这将引入不成熟的优化,却不能带来任何即刻的好处。

显然,在最近几年中这一情况发生了变化。如果查看最新版本的Octane基准测试套件,我们将发现到某些代码的大小已经超过了1MB。这反映出,现实世界里的一些应用正在推动JavaScript引擎逼近其极限。Mandreel基准测试包含了4.8MB的压缩后的代码。为了让这一概念更直观,我们可以以PhotoShop 1.0版本为例,其源代码在解压缩后也只有4.4MB而已。“搅动”这个量级的代码将需要很多时间,特别是在执行例如动画渲染等工作(期望能够在一张眼间完成)时,这将成为显著的问题。

Guo没有试图面面俱到地介绍后台编译,而是告诉我们,在V8中实现这一特性的过程中,他们所面对的一些挑战:

- 每位计算机科学家都会告诉我们,搞定多线程并不是件容易的事情;难以保证测试的良好覆盖;并发固有的不确定性行为,使Bug的重现变得困难,甚至可以说几乎不可能。拥有一套良好的测试用例,使用由断言包含的常量、模糊测试,并且最后很重要的是使用Canary测试覆盖。这些将帮助我们树立起对结果正确与否的信心。顺便说一下,在这里我要向 ThreadSanitizer团队致敬。

-当编译阻塞执行的时候,我们能够确信在编译前后,JavaScript堆及以及其中全部对象的状态将保持一致。然而,面对并行编译,该假设不再成立。这将带来如下影响:

-V8拥有一套负责重新部署的GC,这意味着任何时候一旦GC发挥作用,对象们将被迁移。因此指向这些对象的引用必须得到更新。在执行编译任务的同时,很有可能发生这种情况。而如果编译任务所持有的对象,其引用未能得到更新,那么编译过程最终将内存访问失效的问题。

-在进行并行编译时,执行仍将继续进行。这意味着虚拟机的状态、对象的内容以及布局将能够恣意改变。基于编译任务开始时的情况所做出的假设条件,或许在编译结束时将不再成立。甚至也许编译结束时产出的代码将不再有效。运行这些代码会引发Bug和崩溃。这一现象必须得到妥善处理。

-实际上,允许后台线程在任何时候访问堆,会很容易引发竞争条件。我们通过提前为编译工作收集所有必要的信息来避免这一情况。

-要想找到合适的时机启动后台线程中的编译任务,是一件非常棘手的事情:没有什么方法,能够准确预测是否值得在优化某个代码片段上投入时间,以及是否应该更早完成优化以从中受益。制定启发式解决方案来应对这个问题,则更加困难——必须进行许多精细的调整,而这项工作仍处于进行之中。

-随着源代码片段即将经历的相互关联的状态——例如延迟解析,使用快速编译器进行第一遍编译,接下来由优化编译器进行优化,随后或许会进行“去优化”(deoptimized,如果在编译启动时所做的假设已经不在成立)等等——它的生命周期变得非常复杂。而由于并行编译的出现,这个生命周期中还增加了一些新的状态。对所有状态保持跟踪,确保在状态之间高效转移而不出Bug,是件很复杂的工作。未经预料的极端情况可能会引发问题。

Guo表示,“V8正处于积极发展的阶段,并且正在稳步改进”。例如,大家可以在由Dart维护的实时性能图表格中看到,V8的表现在2月11日运行的DeltaBlue基准测试出现了30%的飞跃——这一结果来自编译器本身的优化,而不是后台编译。

查看英文原文:Challenges Performing Background Compilation in V8

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT