v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化。本文会介绍其中最值得注意的几个。
支持塞住模式的可写流
现在可写流可以支持“塞住(corked)”模式,类似于你执行man tcp
时见到的socket选项TCP_CORK
和TCP_NOPUSH
。
当被塞住时,写到流中的数据会排队直到流被重新开塞(uncorked)。这样Node.js可以将比较小的写操作合并成比较大的,从而减少系统调用和TCP往返。
http模块已经升级了,在发送分块的请求或响应主体时透明地使用塞住模式。如果你经常看看strace(1) 输出,就会发现writev(2)系统调用更多了,而write(2)变少了。
提升TLS性能
tls模块在Node.js v0.12中做了相当大的重构。
在Node.js v0.10中,tls模块在net模块之上,作为对网络流量透明地加密和解密的传输流。从工程角度来看,这样分层是有必要的,但会导致开销-更多的内存转移以及在V8 VM中超出绝对必要的调入调出–并妨碍优化。
所以在node.js v0.12中,直接用libuv重写了tls模块。现在它直接把接入的网络流量拉出来加密,无需通过中间层。
尽管这种评测不太科学,但用空密码时表明现在TLS一般要快10%,并且用的内存更少。(我得说减少的内存占用可能部分是因为重构的内存管理,这是v0.12的另一项优化。)
(还有,如果你想知道,空密码时不会对负载加密的密码;它们可以用来测量架构和协议的开销。)
对于最终用户来说,tls模块的大部分变化都是透明的。其中最显眼的一个是现在TLS连接是从tls.TLSSocket
,而不是tls.CryptoStream
中得到的。
提升Crypto性能
几种加解密算法现在应该更快了,有时是快很多。先介绍下背景:
Node.js中的加解密使用OpenSSL库实现的。OpenSSL中的算法有用C编写,并针对各种平台和架构的手动程序集版本。
Node.js v0.10已经给一些东西用上了程序集版本,而v0.12又大范围扩充了这一范围。此外,现在在有CPU支持时用上了AES-NI,过去三四年生产的大多数x86处理器都支持。
在Linux上,如果执行grep ^flags /proc/cpuinfo | grep -w aes
找到任何匹配结果,那就说明你的系统支持AES-NI。不过像VMWare或VirtualBox之类的虚拟机管理程序可能会对客户机操作系统隐藏CPU的真正能力,包括AES-NI。
启用AES-NI有个有趣的结果,即像AES128-GCM-SHA256这种工业强度的加解密现在比NULL-MD5这样的非加密密码还要快很多!
减少垃圾收集的应激反应
多情景重构的一个副作用是极大减少了Node.js核心中的持久句柄的数量。
持久句柄是对V8堆上对象的强引用,防止对象在引用再次移除之前被垃圾收集器回收(按GC的说法,它是一个人造的GC根。)
Node.js用持久句柄缓存经常使用的值,比如strings或object原型。然而持久句柄在垃圾收集器中需要一个特殊的后处理步骤,并且根据句柄数量有一个线性增长的开销。
因为多情景清理的作用,大部分持久句柄或者被消掉,或者切换成一个更轻量的机制(被称为'永恒句柄';这个名字在暗示什么呢?)
最终效果是你的程序在垃圾收集器内部所用时间更少了,把更多的时间用在了实际的工作上。现在在node –prof
的输出中v8::internal::GlobalHandles::PostGarbageCollectionProcessing()
出现的次数应该少了很多。
更好的集群性能
Node.js v0.10的cluster模块要靠操作系统给工人进程均匀地分发接入连接。
事实证明,在Solaris和Linux上,有些工作负载在工人进程之间分散地非常不均衡。为了缓解这种状况,Node.js v0.12已经改了,默认使用轮转法。这篇文章中有更详细的介绍。
更快的计时器,更快的setImmediate()
,更快的process.nextTick()
setTimeout()
和它的朋友们现在用的时间源不仅更快,而且对时钟偏移免疫。这一优化在所有平台上都启用了,但在Linux上我们更进一步,直接从VDSO上读取当前时间,因此极大降低了gettimeofday(2)
和clock_gettime(2)
系统调用的次数。
setImmediate()
和process.nextTick()
也给通常情况下的派发添加了快速的路径,可以见到性能上的调整。也就是说虽然这些函数已经相当快了,但它们现在更快了。
作者简介
本文最初由Ben Noordhuis发表在StrongLoop上。Ben Noordhuis从2010年就跟着Ryan Dahl开发Node.js的核心代码。他一直在为改进Node核心代码而努力做着编码、调试和基准测试等工作。作为最高产的Node核心开发者之一,Ben编写了Node.js和libuv中的很多代码。StrongLoop降低了在Node中开发APIs的难度,还添加了监测、集群化以及私有注册的支持等DevOps能力。
Node.js V0.12新特性之性能优化的更多相关文章
-
Node.js V0.12 新特性之性能优化
v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化. 本文会介绍其中最值得注意的几个. http://www.infoq. ...
-
【译】 Node.js v0.12的新特性 -- 性能优化
原文: https://strongloop.com/strongblog/performance-node-js-v-0-12-whats-new/ January 21, 2014/in Comm ...
-
【译】 Node.js v0.12的新特性 -- Cluster模式采用Round-Robin负载均衡
原文:https://strongloop.com/strongblog/whats-new-in-node-js-v0-12-cluster-round-robin-load-balancing 本 ...
-
php8.0正式版新特性和性能优化学习
前言 PHP团队宣布PHP8正式GA(链接).php的发展又开启了新的篇章,PHP8.0.0版本引入了一些重大变更及许多新特性和性能优化机制.火速学习下~ JIT(Just in Time Compi ...
-
php7和PHP5对比的新特性和性能优化
1 抽象语法树( AST) 1)在 PHP5中,从 php 脚本到 opcodes 的执行的过程是: Lexing:词法扫描分析,将源文件转换成 token 流: Parsing:语法分析,在 ...
-
Node.js v0.10.31API手冊-控制台
Node.js v0.10.31API手冊-文件夹 控制台 Object 用于向 stdout 和 stderr 打印字符.类似于大部分 Web 浏览器提供的 console 对象函数,在这里则是输出 ...
-
Node.js v0.10.31API手冊-事件
Node.js v0.10.31API手冊-文件夹 Events(事件) Node里面的很多对象都会分发事件:一个net.Server对象会在每次有新连接时分发一个事件, 一个fs.readStrea ...
-
atitit.Oracle 9 10 11 12新特性attilax总结
atitit.Oracle 9 10 11 12新特性 1. ORACLE 11G新特性 1 1.1. oracle11G新特性 1 1.2. 审计 1 1.3. 1. 审计简介 1 1.4. ...
-
UFT\QTP 12 新特性
UFT\QTP 12 新特性 http://blog.csdn.net/testing_is_believing/article/details/22310297
随机推荐
-
硬件抽象层——HAL
(一)为什么要在android中加入HAL Linux系统中Linux驱动有两种类型的代码:访问硬件寄存器的代码——调用的Linux内核的标准函数进行的标准操作 业务逻辑代码——有些企业或个人并不想 ...
-
Android中Intent传值与Bundle传值的区别详解
Android中Intent传值与Bundle传值的区别详解 举个例子我现在要从A界面跳转到B界面或者C界面 这样的话 我就需要写2个Intent如果你还要涉及的传值的话 你的Intent就要写两 ...
-
迭代器模式-Iterator(Java实现)
迭代器模式-Iterator 用于访问一个集合中的各个元素, 而又不会暴露集合的内部的细节. 本文展示的例子就是, 在猫群组里, 用迭代器遍历每一只猫. 本文章的例子的继承关系图如下: 其中: Cat ...
-
QTP - 描述性编程
描述性编程: 1.QTP的描述性编程能够摆脱测试对象库的限制,编写出更为复杂.适应能力更强的测试脚本. 2.即不需要在仓库晨定义,也能访问和操作实际对象. 3.用描述性编程编写的测试脚本在运行时,QT ...
-
【Python】【BugList13】req = requests.get(url=target)报错: (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)')
[代码] # -*- coding:UTF-8 -*- import requests if __name__ == '__main__': target = 'https://unsplash.co ...
-
memset()函数
memset需要的头文件 <memory.h> or <string.h> memset <wchar.h> wmemset 函数介绍 void *memset( ...
-
JAVA的PreparedStatement和addBatch()方法
本文介绍两个内容,为什么使用PreparedStatement的addBatch()方法?以及使用PreparedStatement的好处. 一.addBatch使用方法 昨天用JAVA做了一个导表的 ...
-
利用SpringCloud搭建一个最简单的微服务框架
http://blog.csdn.net/caicongyang/article/details/52974406 1.微服务 微服务主要包含服务注册,服务发现,服务路由,服务配置,服务熔断,服务降级 ...
-
MongoDB中的数据导出为excel CSV 文件
1.打开命令行,进入我们所安装的mongodb路径下的bin文件夹 2.我们采用bin文件夹下的mongoexport方法进行导出, mongoexport -d myDB -c user -f _i ...
-
疯狂Android讲义
1 Android应用和开发环境2 Android应用的界面编程3 Android的事件处理4 Activity Fragment5 Intent IntentFilter6 Android应用的资源 ...