新 V8 推出后 Node.js 性能有何变化
沉沙 2018-07-19 来源 : 阅读 785 评论 0

摘要:本篇Node.js教程探讨了新 V8 推出后 Node.js 性能有何变化,希望阅读本篇文章以后大家有所收获,帮助大家对Node.js的理解更加深入。

自从诞生以来,Node.js 就依赖于 V8 引擎, V8 引擎是由 Google 为 Chrome 浏览器编写的 JavaScript 虚拟机。从一开始,V8 的主要目标就是使 JavaScript 运行更加快速,或至少比竞争对手快。对于高度动态这并不容易。这部分是关于 V8 和 JS 引擎性能的演变。

V8 引擎的核心部分是能够高速执行 JavaScript 的 JIT(Just In Time)编译器。这是一个动态编译器,可以在运行时优化代码。当 V8 最初构建时,JIT 编译器被称为 FullCodegen。然后,V8 团队实现了 Crankshaft,其中包括许多 FullCodegen 未实现的性能优化。

从 90 年代开始,JavaScript 哪些操作快,哪些操作慢(无论引擎是什么)通常都是反直觉的,所以JavaScript 代码慢的原因常常难以理解。

近年来,Matteo Collina 和我专注于如何编写性能优异的 Node.js 代码。当然,这意味着当 V8 引擎执行代码时,要知道哪些方法是快速的,哪些方法很慢。

现在是我们挑战所有关于性能假设的时候了,因为 V8 团队已经编写了一个新的 JIT 编译器:Turbofan。

从常见的“V8杀手”开始,到更复杂的 Matteo 和我对 Crankshaft 性能的发现,我们将会根据一系列测试结果来对 V8 进行评估。

当然,在优化 V8 代码之前,我们应该首先关注 API 设计,算法和数据结构(过早的优化是万恶之源)。下面会对 Node 的几个版本进行性能测试。我们可以得到一些结论来影响我们的代码风格,以及在应用通常的优化后提高性能的方式。

Try / Catch 问题

一个非常出名的去优化模式是使用 try/catch blocks.

测试代码链接 分别测试如下 4 种情况

· 函数中有 try/catch

· 函数中不带 try/catch

· 在 try 中调用函数

· 调用函数(没有 try/catch)

测试数据

 

我们可以看到 node 6 ( V8 5.1 ) 中 try/catch 的性能问题确实存在,但在 node 8 到 node 8.2 得到明显的改善。

另外值得注意的是, 在 try block 中调用函数明显比在 try block 外面要慢。

到 node 8.3 以上的版本 try/catch 对调用函数的影响基本可以忽略不计。

删除对象的属性

由于 javascript 对象的动态特性和原型链,导致属性查找更加复杂。

这里使用 3 种方式删除对象属性(测试代码)。

· 通过设置直接给对象属性设为 undefined

· 通过 delete 删除属性

· 删除最近添加的属性

 

在 Turbofan (V8 6.0 and 6.1)可以发现删除最近添加属性的效率更高,通过给对象属性直接设为 undefined 的效率也是非常高的。而 delete 操作在大部分情况表现不佳。

Arguments

普通的 JavaScript 函数可用隐式参数对象,它很像数组。

为了使用数组方法或大多数数组行为,参数对象的索引属性已被复制到数组中。在过去,JavaScript 中人们倾向于将较少的代码等同于与较快的代码。虽然这个经验法则为浏览器端代码带来了有效负载的好处,但同样的规则导致了服务器端代码大小远不如其执行速度重要的痛苦。所以将参数对象转换为数组的一种简洁方法就变得非常受欢迎:

Array.prototype.slice.call(arguments)。这调用 Array slice 方法传递参数对象作为该方法的上下文,slice 方法会得到一个像数组一样的对象,并相应地执行。也就是说,它将整个参数array-like 对象作为一个数组。

但是,当函数的隐式参数对象从函数上下文中暴露出来(例如,当从函数返回或传递到另一个函数中时,如 Array.prototype.slice.call(arguments)所示),这通常会导致性能下降。

测试代码

· 暴露 arguments 对象给其他的函数

· 使用 Array.prototype.slice 复制 arguments 对象

· 使用循环复制对象的每一个属性

· 使用 es6 的展开操作符

 

我们再把这些数据转化成折线图:

 

如果我们想要将函数输入的参数写成一个数组,在 Node 8.3 以上版本我们建议使用 spread 操作符。在 Node 8.2 及以下版本我们最好通过循环复制对象属性到一个新的数组以提升性能。

对于 node 8.3 及以上版本,将参数对象直接暴露给其他的函数的情况性能表现很不错,因此在不需要把参数写成数组,这种方式可以大大提升代码执行效率。

 

本文由职坐标整理并发布,了解更多内容,请关注职坐标WEB前端Node.js频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程