从 V8 优化看高效 JavaScript

简介: 从 V8 优化看高效 JavaScript

理解 JavaScript 是如何工作的对于编写高效的 JS 大有帮助。


V8 执行 JS 分为三个阶段:

  • 源代码转换为 AST 抽象语法树。
  • 语法树转换为字节码:这个过程由 V8 的 Ignition 完成,2017年之前是没有的。
  • 字节码编译成机器码:由 V8 的编译器 TurboFan 来完成。


第一个阶段并不是文本的讨论范围,第二三阶段对于编写优化 JS 有直接影响。


实际上第二三阶段是紧耦合的,它们都在 just-in-time( JIT )内运作。为了理解 JIT ,我们先回顾下源代码转换为机器码的两种方法:1、解释器

解释器逐行转换和执行代码,其优点是易于实现和理解、及时反馈、更宽泛的编程环境,缺点也非常明显,那就是速度慢,慢的原因在于(1)反复解释的开销和(2)无法优化程序的各个部分。

换句话说,解释器在处理不同的代码段时无法识别重复的工作量。如果你通过解释器运行相同的代码 100 次,那么解释器将会翻译并执行相同的代码 100 次,其中不必要的重新翻译了 99 次。

解释器很简单、启动快速,但执行速度慢。

2、编译器编译器在执行之前翻译所有的源代码。编译器更加复杂,但是可以进行全局优化(例如,共享重复代码),其执行速度也更快。

编译器更复杂、启动慢,但执行速度更快。

JIT 的作用就是尽可能结合解释器和编译器的优点,以使翻译代码和执行都能快速。

基本思想是尽可能避免重新翻译。首先,探测器通过解释器运行代码,在执行期间,探测器会追踪代码段并将其会被划分为 warm(运行少数几次) 和 hot(运行重复多次)。

JIT 把 warm 代码段直接丢给基准编译器,尽可能重用已编译的代码。

JIT 把 hot 代码段丢给优化编译器,其根据解释器收集来的信息(1)作出假设,(2)基于假设(比如,对象属性始终以特定顺序出现)进行优化。然而,一旦假设不成立,优化编译器就会进行 deoptimization 去优化,就是丢弃优化的代码。


优化和去优化的周期是昂贵的。由于需要存储优化过的机器码和探测器的信息,JIT 引入了额外的内存成本。这种成本激发了 V8 的解释器 Ignition 。


Ignition 将 AST 转换为字节码,字节码序列被执行,其反馈信息被 inline caches 内联高速缓存。 反馈信息被用于(1)Ignition 随后的解释,和(2)TurboFan 推测性优化。TurboFan 基于反馈推测性的优化将字节码转换为机器码。


...


如何优化你的 JavaScript


1、在构造函数中声明对象属性


改变对象的属性将会导致新的隐藏类:本来 p1 和 p2  应该使用的是同一个隐藏类,但是由于 p1.z 的原因将会导致它们使用不同的隐藏类,这将导致 TurboFan 的去优化,这是应该避免的。


2、保持对象属性排序不变


改变对象属性的排序也将会导致新的隐藏类:


保持对象属性的排序有利于重用相同的隐藏类,效率更高。


3、注意函数的参数类型


函数参数类型的更改也将会导致去优化和重新优化:比如这个函数,由于参数类型的易变将会导致编译器无法优化。


4、在 script 域声明类


不要在函数范围内定义类:

这个函数每被调用一次,一个新的原型就被会创建,每个新的原型都会对应一个新的对象 shape ,这也是无法优化的。


5、使用 for ... in


for ... in 循环是 V8 引擎特别优化过的,可以快 4 到 6 倍。


6、不相关的字符不会影响性能


早期使用的是函数的字节计数来确定是否内联函数,但是现在使用的是 AST 的节点数量来确定函数的大小。这就是说,诸如空格、注释、变量名称长度、函数签名之类的不相关字符不会影响函数的性能。


7、Try / catch / finally 并不是毁灭性的


Try 以前会导致昂贵的优化和去优化循环,但是现在并不会导致明显的性能影响。

目录
相关文章
|
6月前
|
监控 负载均衡 JavaScript
有哪些有效的方法可以优化Node.js应用的性能?
有哪些有效的方法可以优化Node.js应用的性能?
357 69
|
6月前
|
监控 算法 JavaScript
公司局域网管理视域下 Node.js 图算法的深度应用研究:拓扑结构建模与流量优化策略探析
本文探讨了图论算法在公司局域网管理中的应用,针对设备互联复杂、流量调度低效及安全监控困难等问题,提出基于图论的解决方案。通过节点与边建模局域网拓扑结构,利用DFS/BFS实现设备快速发现,Dijkstra算法优化流量路径,社区检测算法识别安全风险。结合WorkWin软件实例,展示了算法在设备管理、流量调度与安全监控中的价值,为智能化局域网管理提供了理论与实践指导。
181 3
|
5月前
|
JavaScript
JS代码的一些常用优化写法
JS代码的一些常用优化写法
108 0
|
9月前
|
前端开发 JavaScript Java
JavaScript闭包深入剖析:性能剖析与优化技巧
JavaScript 闭包是强大而灵活的特性,广泛应用于数据封装、函数柯里化和事件处理等场景。闭包通过保存外部作用域的变量,实现了私有变量和方法的创建,提升了代码的安全性和可维护性。然而,闭包也可能带来性能问题,如内存泄漏和执行效率下降。为优化闭包性能,建议采取以下策略:及时解除对不再使用的闭包变量的引用,减少闭包的创建次数,使用 WeakMap 管理弱引用,以及优化闭包结构以减少作用域链查找的开销。在实际开发中,无论是 Web 前端还是 Node.js 后端,这些优化措施都能显著提升程序的性能和稳定性。
239 70
|
6月前
|
人工智能 监控 前端开发
基于 Next.js 的书法字体生成工具架构设计与 SSR 优化实践
本项目是一款书法字体生成工具,采用 Next.js 14(App Router)与 Tailwind CSS 构建前端,阿里云 Serverless 部署后端。通过混合渲染策略(SSG/SSR/CSR)、Web Worker 异步计算及 CDN 字体分片加载优化性能。服务端借助阿里云函数计算处理计算密集型任务,将平均耗时从 1200ms 降至 280ms,支持 1000+ QPS。动态路由与 ARMS 监控提升工程化水平,未来计划引入 WebGPU 和 AI 字体风格迁移技术,进一步优化用户体验。
|
8月前
|
前端开发 JavaScript
【Javascript系列】Terser除了压缩代码之外,还有优化代码的功能
Terser 是一款广泛应用于前端开发的 JavaScript 解析器和压缩工具,常被视为 Uglify-es 的替代品。它不仅能高效压缩代码体积,还能优化代码逻辑,提升可靠性。例如,在调试中发现,Terser 压缩后的代码对删除功能确认框逻辑进行了优化。常用参数包括 `compress`(启用压缩)、`mangle`(变量名混淆)和 `output`(输出配置)。更多高级用法可参考官方文档。
630 11
|
8月前
|
JavaScript 前端开发 算法
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
10月前
|
前端开发 JavaScript
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
303 14
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
8月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
10月前
|
缓存 NoSQL JavaScript
Vue.js应用结合Redis数据库:实践与优化
将Vue.js应用与Redis结合,可以实现高效的数据管理和快速响应的用户体验。通过合理的实践步骤和优化策略,可以充分发挥两者的优势,提高应用的性能和可靠性。希望本文能为您在实际开发中提供有价值的参考。
261 11