热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

TurboFan的故事

2017年2月份Google宣布将会在Chrome59中启用IgnitionTurboFan流水线。距离Google在2013年开始TurboFan计划已经过去了三年半。在2013

2017年2月份Google宣布将会在Chrome 59中启用Ignition+TurboFan流水线。距离Google在2013年开始TurboFan计划已经过去了三年半。在2013年末时,TurboFan团队坚信需要处理Crankshaft的代码生成问题并且throw more sophisticated peak performance optimizations at Javascript code。We based most of these findings on Javascript code we hit in certain benchmarks like Octane and investigations of asm.js based applications, but also on findings from important web pages like Google Maps.这些都被认为是真实世界表现中的一种较好的模拟,因为它们给优化编译器带来了很大的压力。但是现在往回看,当时的许多想法都是错误的。尽管更聪明的编译器能更好适应Octane中的许多测试,现实是对于绝大多数网站来说优化编译器并不重要,有时甚至会使得性能受损——因为特定类型的优化有时间开销——尤其是在移动设备上的页面加载阶段。

但是TurboFan研发的第一年团队没有考虑真实世界中的场景。最初的目标是构建一个全语言编译器,能够在asm.js类似的代码上运行良好——这两个目标都是Crankshaft无法做到的。在Chrome 41中我们shipped TurboFan for asm.js代码。这个TurboFan的初始版本已经包含了大量smartness。We basically got to Firefox level of asm.js performance with a more general approach。Most of the type based optimizations for fast arithmetic would work equally well in general Javascript. 从个人视角看,那个时候的TurboFan优化编译器可能是最优美的版本,这也是唯一的一个版本(对于一个Javascript编译器来说)where I could imagine that a “sea of nodes” approach might make sense (although it was already showing its weakness at that time)。在接下来的几个月内我们尝试find incremental ways to turn TurboFan into a viable, general drop-in replacement for Crankshaft。But we struggled to find another subset of Javascript that would be possible to tackle independently, similar to how we started with asm.js。

在2015年中期我们开始意识到TurboFan可能在解决我们不会遇到的问题,and that we might need to go back to the drawing board to figure out why V8 is struggling in the wild. We weren’t really engaging the community at that time, and my personal response when developers brought problems to my attention was often negative and along the lines of “your Javascript does odd things”, which over time turned into “if your code is slow in V8, you wrote slow code” in people’s minds. So taking a step back, and trying to understand the full picture, I slowly realized that a lot of the suffering arose from performance cliffs in V8. Phrased differently, we were over-focused on the peak performance case, and baseline performance was a blind spot.

这种对于平衡的缺失会导致高度不可预测的性能。例如,当Javascript代码遵循特定的模式,⸺ avoid all kinds of performance killers, keep everything monomorphic, limit the number of hot functions ⸺ you’ll be able to squeeze awesome performance out of V8, easily beating Java performance on similar code. But as soon as you leave this fine line of awesome performance, you often immediately fall off a steep cliff.

V8就像悬崖一样性能变化极其明显,在过去,100倍的性能变化是很常见的。Of these cliffs, the arguments object handling in Crankshaft is probably the one which people hit most often and which is the most frustrating too。Crankshaft中的一个最基本的假设是arguments object does not escape, and thus Crankshaft does not need to materialize the actual Javascript arguments object ever, but instead can just take the parameters from the activation record. So, in other words, there’s no safety net. It’s all or nothing. Let’s consider this simple dispatching logic:

var callbacks = [function sloppy() {},function strict() {"use strict";}
];function dispatch() {for (var l &#61; callbacks.length, i &#61; 0; i < l; &#43;&#43;i) {callbacks[i].apply(null, arguments);}
}for (var i &#61; 0; i < 100000; &#43;&#43;i) {dispatch(1, 2, 3, 4, 5);
}

Looking at it naively, it seems to follow the rules for the arguments object in Crankshaft: In dispatch we only use arguments together with Function.prototype.apply. Yet, running this simple example.js in node tells us that all optimizations are disabled for dispatch:

$ node --trace-opt example.js
...
[marking 0x353f56bcd659 <JS Function dispatch (SharedFunctionInfo 0x187ffee58fc9)> for optimized recompilation, reason: small function, ICs with typeinfo: 6/7 (85%), generic ICs: 0/7 (0%)]
[compiling method 0x353f56bcd659 <JS Function dispatch (SharedFunctionInfo 0x187ffee58fc9)> using Crankshaft]
[disabled optimization for 0x167a24a58fc9 <SharedFunctionInfo dispatch>, reason: Bad value context for arguments value]

The infamous Bad value context for arguments value reason. So, what is the problem here? Despite the code following the rules for arguments object, it falls off the performance cliff. The real reason is pretty subtle: Crankshaft can only optimize fn.apply(receiver,arguments) if it knows that fn.apply is Function.prototype.apply, and it only knows that for monomorphic fn.apply property accesses. That is, fn has to have exactly the same hidden class ⸺ map in V8 terminology ⸺ all the time. But callbacks[0] and callbacks[1] have different maps, since callbacks[0] is a sloppy mode function, whereas callbacks[1] is a strict mode function:

$ cat example2.js
var callbacks &#61; [function sloppy() {},function strict() { "use strict"; }
];
console.log(%HaveSameMap(callbacks[0], callbacks[1]));
$ node --allow-natives-syntax example2.js
false

TurboFan on the other hand happily optimizes dispatch (using the latest Node.js LKGR):

$ node --trace-opt --future example.js
[marking 0x20fa7d04cee9 <JS Function dispatch (SharedFunctionInfo 0x27431e85d299)> for optimized recompilation, reason: small function, ICs with typeinfo: 6/6 (100%), generic ICs: 0/6 (0%)]
[compiling method 0x20fa7d04cee9 <JS Function dispatch (SharedFunctionInfo 0x27431e85d299)> using TurboFan]
[optimizing 0x1c22925834d9 <JS Function dispatch (SharedFunctionInfo 0x27431e85d299)> - took 0.526, 0.513, 0.069 ms]
[completed optimizing 0x1c22925834d9 <JS Function dispatch (SharedFunctionInfo 0x27431e85d299)>]
...

推荐阅读
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 安卓select模态框样式改变_微软Office风格的多端(Web、安卓、iOS)组件库——Fabric UI...
    介绍FabricUI是微软开源的一套Office风格的多端组件库,共有三套针对性的组件,分别适用于web、android以及iOS,Fab ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • 小程序wxs中的时间格式化以及格式化时间和date时间互转
    本文介绍了在小程序wxs中进行时间格式化操作的问题,并提供了解决方法。同时还介绍了格式化时间和date时间的互相转换的方法。 ... [详细]
  • JavaScript简介及语言特点
    本文介绍了JavaScript的起源和发展历程,以及其在前端验证和服务器端开发中的应用。同时,还介绍了ECMAScript标准、DOM对象和BOM对象的作用及特点。最后,对JavaScript作为解释型语言和编译型语言的区别进行了说明。 ... [详细]
  • 正则表达式及其范例
    为什么80%的码农都做不了架构师?一、前言部分控制台输入的字符串,编译成java字符串之后才送进内存,比如控制台打\, ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • Google在I/O开发者大会详细介绍Android N系统的更新和安全性提升
    Google在2016年的I/O开发者大会上详细介绍了Android N系统的更新和安全性提升。Android N系统在安全方面支持无缝升级更新和修补漏洞,引入了基于文件的数据加密系统和移动版本的Chrome浏览器可以识别恶意网站等新的安全机制。在性能方面,Android N内置了先进的图形处理系统Vulkan,加入了JIT编译器以提高安装效率和减少应用程序的占用空间。此外,Android N还具有自动关闭长时间未使用的后台应用程序来释放系统资源的机制。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
author-avatar
衢江大道
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有