您的位置:首页 > Web前端 > Node.js

Node.js V0.12新特性之性能优化

2015-04-09 11:05 316 查看

v0.12悠长的开发周期(已经过去九个月了,并且还在继续,是有史以来最长的一次)让核心团队和贡献者们有充分的机会对性能做一些优化。本文会介绍其中最值得注意的几个。

支持塞住模式的可写流

现在可写流可以支持“塞住(corked)”模式,类似于你执行
man
tcp
时见到的socket选项
TCP_CORK
TCP_NOPUSH

当被塞住时,写到流中的数据会排队直到流被重新开塞(uncorked)。这样Node.js可以将比较小的写操作合并成比较大的,从而减少系统调用和TCP往返。

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()
也给通常情况下的派发添加了快速的路径,可以见到性能上的调整。也就是说虽然这些函数已经相当快了,但它们现在更快了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: