V8是如何快速地解析JavaScript延迟解析
如前所述,打包器通常通过将模块代码封装在一个它们即时调用的闭包中,来将多个模块组合到一个文件中。这为模块提供了隔离,允许它们像脚本中唯一的代码一样运行。这些函数本质上是嵌套的脚本;脚本执行时这些函数会立即被调用。打包器通常以带圆括号的函数,即 (function(){…})(),的形式提供即时调用函数表达式(IIFEs,发音为“iffies”)。 由于这些函数在脚本执行期间是立即需要的,所以预解析这些函数并不理想。在脚本的顶层执行过程中,我们急需这些函数被编译,所以我们会完全解析和编译这些函数。这意味着,我们在前期解析越快,代码运行时启动就越快,并且不会产生不必要的额外成本。 你可能会问,为什么不直接编译调用的函数呢?虽然开发人员在一个函数被调用时能很容易注意到它,但是对于解析器情况则不同。解析器在开始解析函数之前需要决定该函数是需要立即编译还是推迟编译。语法中存在的歧义使得简单地快速扫描到函数末尾变得很困难,而且成本很快就与常规预解析的成本一样。 因此V8有两个简单的模式,它可以将函数识别为随时调用函数表达式(PIFEs,发音为“piffies”),这样它会快速解析并编译一个函数: 如果一个函数是一个带圆括号的函数表达式,即(function(){…}),我们假设它将被调用。我们一看到这个模式的开始,即(function,就立即做出这个假设。 在V8 v5.7 / Chrome 57中我们也检测了由UglifyJS生成的模式!function(){…}(),function(){…}(),function(){…}()。一旦我们看到!function或者function后面如果紧跟着一个PIFE,那么这个检测就起作用了。 由于V8会立即编译PIFEs,所以它们可以被用作配置文件导向的反馈[2],通知浏览器启动需要哪些函数。 当V8还在预解析内部函数时,一些开发人员已经注意到JS解析对启动的影响相当大。optimize-js包会基于静态启发式将函数转换为PIFEs。这个包的创建对V8的负载性能有很大的影响。通过在V8 v6.1上运行optimize-js提供的基准测试,我们复制了这些结果,你只需要查看缩小的脚本。 ![]() 急切地解析和编译PIFEs会导致冷启动和热启动稍微快一些 (第一和第二页加载,测量总的解析+编译+执行时间)。但是,由于对解析器的显著改进,这在V8 v7.5上的好处要比在V8 v6.1上使用的好处小得多。 (编辑:西安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |