JS引擎V8如何与 Lite 模式两开花?

时间: 2019-09-08阅读: 309标签: 引擎

去年年底,V8 团队启动了一个名为 V8 Lite 的项目,旨在大幅降低 V8 的内存使用率。最开始,团队准备把 V8 Lite 作为 V8 的独立模式,专门用于低内存的移动设备与嵌入式设备,因为这些设备更关注的是减少内存使用而不是执行速度。

在这个项目研发的过程中,开发团队发现专门为这个 Lite 模式所做的内存优化其实也可以迁移到原来的 V8 上,直接两开花。V8 团队近日发表了一个文章,就详细分享了在构建 V8 Lite 的过程中将一些关键的优化部分带到现有 V8 上的过程,以及在实际工作负载中对 V8 性能表现的影响。下边简要介绍一下。


Lite Mode(轻量模式)

分析了 V8 如何使用内存以及哪些对象类型占 V8 堆大小的比例很大之后,V8 团队发现,V8 堆的很大一部分专门用于对 JavaScript 执行来说不必要的对象,比如用于优化 JavaScript 执行和处理异常情况。具体来说比如优化代码;用于确定如何优化代码的类型反馈;用于 C++ 和 JavaScript 对象之间绑定的冗余元数据等。


所以团队从这一点入手,想通过大幅减少这些可选对象的内存分配来提高内存使用。同时团队提出了 V8 的 Lite Mode。


通过配置现有的 V8 设置可以直接应用一些 Lite Mode 的优化,例如禁用 V8 的 TurboFan 优化编译器,但是现有 V8 想支持其它 Lite Mode 优化则需要更多的考虑。

比如在 Ignition 解释器中执行代码时,V8 收集有关传递给各种操作(例如,+o.foo)的操作数类型的反馈,以便为以后的优化定制这些类型。此信息存储在反馈向量中,这些向量占 V8 堆内存使用量的很大一部分。Lite Mode 不优化代码,所以可以直接不去分配这些反馈向量,但是 V8 的内联缓存基础结构的解释器期望反馈向量可用,因此需要相当多的重构才能支持 Lite Mode 这种无反馈执行。

Lite Mode 在 V8 v7.3 中推出,与 V8 v7.1 相比,通过禁用代码优化、不分配反馈向量并执行很少执行的字节码老化,典型网页堆大小减少 22%。

同时在这个过程中,团队还发现,可以通过使 V8 更加“Lazy”来实现 Lite Mode 的大部分内存节省,而不会影响性能。


Lazy feedback allocation (惰性反馈分配)

完全禁用反馈向量分配不仅会阻止 V8 的 TurboFan 编译器优化代码,还会阻止 V8 执行常见操作的内联缓存,例如 Ignition 解释器中的对象属性加载。因此,这样做会导致 V8 的执行时间显著回退,页面加载时间减少 12%,典型交互式网页方案中 V8 使用的 CPU 时间增加 120%。

为了在没有这些回退的情况下将大部分内存节省带到常规 V8 中,开发团队设计了在函数执行了一定量的字节码(目前为 1KB)之后,延迟分配反馈向量。由于大多数函数不经常执行,因此在大多数情况下避免使用反馈向量分配,但会在需要的地方快速分配它们以避免性能回退,并仍然允许优化代码。

使用这种方法,会产生另一个问题。反馈向量会形成树结构,内部函数的反馈向量被保留为外部函数的反馈向量中的条目。这是必要的,以便新创建的函数闭包接收与为同一函数创建的所有其它闭包相同的反馈向量数组。在延迟分配反馈向量的情况下,无法使用反馈向量来形成这棵树,因为无法保证外部函数会在内部函数分配其反馈向量之前就对其进行分配。

如下图,为了解决这个问题,开发团队创建了一个新的 ClosureFeedbackCellArray 来维护这个树,当一个函数的 ClosureFeedbackCellArray 变为 Hot 时将其与一个完整的 FeedbackVector 交换掉。


实验显示桌面延迟反馈没有出现性能回退,而在移动端,由于垃圾回收减少,性能有所提升,因此 V8 所有版本中都启用了延迟反馈分配。


Lazy source positions

从 JavaScript 编译字节码时,会生成源位置表,将字节码序列绑定到 JavaScript 源代码中的字符位置。但是,仅在表示异常或执行开发人员任务(如调试)时才需要此信息,因此很少使用。

为了避免这种浪费,现在编译字节码而不收集源位置(假设没有附加调试器或分析器)。仅在实际生成堆栈跟踪时收集源位置,例如在调用 Error.stack 或将异常的堆栈跟踪打印到控制台时。这需要一些成本,因为生成源位置需要重新分析和编译函数,但是大多数网站不会在生产中对堆栈跟踪进行符号化,因此不会看到什么性能影响。


Bytecode flushing(字节码淘汰)

从 JavaScript 源编译的字节码,包括相关的元数据占用了大量的 V8 堆空间,通常约为 15%。但是有许多函数只在初始化期间执行,或者在编译后很少使用。所以,V8 针对最近没有执行的情况,添加了在垃圾回收期间支持从函数中刷新已编译字节码的功能。

具体机制是,跟踪函数字节码的 age,每次主要(mark-compact)垃圾回收 age 都递增,并在执行函数时将其重置为零。任何超过老化阈值的字节码都可以被下一次垃圾回收回收,如果它被回收然后再次执行,则会重新编译。

这么设计的难点在于确保字节码仅在不再需要的情况下才可以被刷新。例如,如果函数 A 调用另一个长时间运行的函数 B,函数 A 可能会在它仍然在堆栈上时老化。这时候我们并不想刷新函数 A 的字节码,即使它达到了老化阈值,因为还需要在长时间运行的函数 B 返回时返回它。

解决这个问题的方法是,当字节码达到其老化阈值时,将字节码视为弱保持状态(weakly held),但是在堆栈或其它地方对字节码的任何引用将强烈保持(strongly held),并且只在没有强链接的情况下才可以刷新代码。

除了刷新字节码,同时还刷新与这些刷新函数相关的反馈向量。但是,无法在与字节码相同的 GC 周期内刷新反馈向量,因为它们不会被同一对象保留。字节码由本地上下文独立的 SharedFunctionInfo 保留,而反馈向量由本地上下文相关的 JSFunction 保留。因此,会在随后的 GC 循环中刷新反馈向量。



额外的优化

此外开发团队还通过减小 FunctionTemplateInfo 对象的大小和对 TurboFan 优化代码进行去优化等方面的优化减少了内存使用。


结果

目前已经在 V8 的最新七个版本中发布了上述优化,通常它们会先应用在 Lite Mode 中,然后再进入 V8 的默认配置。

经过测试,在一系列典型网站上将 V8 堆大小平均减少了 18%,相当于低端 AndroidGo 移动设备平均减少 1.5 MB。

通过禁用功能优化,Lite Mode 可以以一定的开销进一步为 JavaScript 执行吞吐量提供内存节省。平均而言,Lite Mode 可节省 22% 的内存,有些页面可节省高达 32% 的内存。这相当于 AndroidGo 设备上 V8 堆大小减少了 1.8 MB。



 

具体分析每一种优化技术带来的影响,结果如下:


原文链接:https://v8.dev/blog/v8-lite


站长推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入

3.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/5808

模板引擎art-template怎么安装?

art-template支持标准语法和原始语法。标准语法允许模板更易于读写。而原始语法具有强大的逻辑处理能力。标准语法支持基本模板语法和JavaScript表达式。原始语法支持任意JavaScript语句,与EJS相同。

V8 8.0 JavaScript 引擎降低堆内存 40%,添加语言特性 Optional Chaining 和 Null Coalescing

Google 最新发布了 V8 JavaScript 引擎 V8 8.0 ,其中使用压缩指针(pointer compression)技术,在不影响性能的情况下实现堆内存占用降低了 40%。此外,V8 8.0 添加了支持“可选链”(optional chaining)的操作符 ?.

javascript引擎有哪些?

JavaScript引擎是一个专门处理JavaScript脚本的虚拟机,一般会附带在网页浏览器之中。在2008年到2009年的第二次浏览器大战之前,JavaScript引擎(JavaScript engine)仅简单地被当作能阅读执行JavaScript源代码的解释器

百度正式开源转发引擎 BFE,曾支撑春晚红包百亿流量

BFE(Baidu Front End,百度统一前端)是百度的统一七层流量转发平台。据了解,BFE 平台目前已接入百度大部分流量,每日转发请求接近 1 万亿,峰值 QPS 超过 1000 万。

免费搜索引擎提交(登录)入口大全

搜索引擎网站收录地址大全;独立博客收录提交网址;英文搜索网站收录地址;注意:目前搜狗,Soso,迅雷狗狗没有网站提交入口,它们都是由谷歌提供技术支持,基本上只要谷歌收录了它们也会跟风。

20 行代码实现模板引擎

实现功能 : 变量值的替换、if / else 及 for 循环等复杂操作。利用 exec 方法将变量替换为对象属性值,注意此方法输出的是一个数组,形如下方代码。

什么是v8(javascript引擎)?

v8(javascript引擎)是一个专门处理JavaScript脚本的虚拟机,是将Javascript代码处理并执行的运行环境,一般会附带在网页浏览器之中。V8使用C++开发,并在谷歌浏览器中使用。

规则引擎解决方案浅析

用于页面,流程,扩展点实现的选择;输出结果:实现的位置;编排无数的条件积木和行为积木,达到业务逻辑计算,券库存消减的目的;输出结果:商品重计算后的价格;通过订单,售后单,会员等信息编排和判断

Node js 视图引擎

Node js 视图引擎就像 Laravel 中的 Blade。其最基本的定义是,视图引擎是帮助我们用比通常更短、更简单的方式编写 HTML 代码并重用的工具。此外,它还可以从服务器端导入数据并渲染最终的 HTML

从Google V8引擎剖析Promise实现

本文阅读的源码为Google V8 Engine v3.29.45,此版本的promise实现为js版本,在后续版本Google继续对其实现进行了处理。引入了es6语法等,在7.X版本迭代后,逐渐迭代成了C版本实现。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广