精华 ShadowNode v0.9.0 发布
发布于 3 个月前 作者 yorkie 2760 次浏览 来自 分享

喜大奔普,就在昨天 ShadowNode v0.9 发布了!废话不多说,先来看这个版本的更新日志。

英文原版可以看这里:Release Proposal: working on v0.9.x

JerryScript(引擎部分)

  • 支持运行时获取函数名(快照 / 非快照),通过编译时增加 FEATURE_FUNCTION_NAME 开启。
  • 支持 CPU Profiler,可生成性能火焰图,通过 FEATURE_CPU_PROFILER 开启。

构建及自动化

  • Travis: 增加部署阶段(Stage)用于发行二进制包。
  • 使用更加稳定的 Python TestDriver 替换原有的 JavaScript Driver。
  • 移植 Node.js Benchmark 框架到 ShadowNode 中。
  • 增加 Codacy 作为静态代码扫描工具。
  • 提供工具可以查看 ECMAScript 特性支持列表。

启动

  • 修复了每次 Math.random() 随机数序列相同的问题。
  • 修改了命令行工具帮助指令,使其更像是 Node.js。

模块

  • Buffer
    • 增加 readInt32LE() 方法。
    • 增加 writeInt16LE() 方法。
  • Process
    • 增加 process.title 的方式来设置进程名(在 MacOS 上使用由于需要额外加载动态库,所以会出现一定程度的内存增长)。
  • Console
    • 对于单个参数比如 console.log(‘yorkie’) 做了特殊的性能优化。
    • 禁用了 Stdio 缓冲区,与 Node.js 保持一致。
  • Child Process
    • Pipe: 使用 uv_write 替代 uv_try_write,后者会导致出现 EAGAIN 无法处理的情况。
    • 修复了2个内存泄漏问题。
  • Stream
    • writable#write 方法增加 encoding 参数。
  • Net
    • 默认使用 IPv4 作为 DNS 族选项。
  • HTTP
    • 增加 Chunked Transfer,并且默认支持。
    • 根基 Body 大小自动计算 Content-Length 。
  • D-Bus
    • 信号(Signal)支持多参数发送。
    • 修复一个内存泄漏问题。
  • Profiler
    • 新增该模块,用于提供 CPU Profiler 功能。

社区

很开心地宣布两个比较重大的消息。

  • 迎来了以为新的 Committer @Lanfly
  • 这次的更新虽然没有为大家带来 N-API,不过却意外支持了 FFI shadow-node/ffi

没有了小故事的 ShadowNode?

这次小故事放到后面,先给大家分享一些更重要的小教程。

如何使用 FFI

如果不了解 FFI 的同学,可以跳转到 Foreign function interface 查看科普。简单来说,就是让开发者完全使用 JavaScript 来调用一些动态库的函数,下面便是一段调用数学库(libm.so)的代码:

'use strict';
var libm = ffi.Library('libm', {
  'ceil': [ 'double', [ 'double' ] ]
});
assert.strictEqual(libm.ceil(1.5), 2);

更多的例子可以参考:shadow-node/ffi

另外如果你懒得写代码的话,可以使用 tjfontaine/node-ffi-generate,它根据一个头文件生成对应的 JavaScript 代码,ShadowNode FFI 设计之初,就尽量保持了与 node-ffi/node-ffi 的接口兼容性,因此喜欢自动化的同学不妨试试。

在 ShadowNode 上的 CPU Profiling

首先大家可以看看新增的 Profiler 模块,该模块提供了一个方法:startProfiling 用于开启统计。下面是一个比较简单的示例:

'use strict';
var profiler = require('profiler');
profiler.startProfiling();

var testArr = [ 1, 2, 3, 4, 5 ];
for (var i = 0; i < 100; i++) {
  console.log.apply(console, testArr);
}
profiler.stopProfiling();

在运行上述代码之前,需要先使用如下的命令编译开启 CPU Profiler:

$ tools/build.py --install --clean --no-snapshot --jerry-cpu-profiler
$ iotjs test-profiler.js

执行后可以在当前目录下发现一个以 Profile- 开头的文件,如 Profile-1532778664486.183,这个文件就是执行完后生成的 Profile 文件,然后再通过下面的命令即可生成火焰图:

$ tools/profiler/cl.py <profiler文件> dump > result.txt
$ tools/profiler/flamegraph.pl result.txt > result.html

使用浏览器打开后可以看到:

Screen Shot 2018-07-28 at 8.04.24 PM.png

这样便可以通过火焰图分析性能瓶颈了。当然大家现在可以看到,现在有很多类似 536、1998 这样的数字,这些是目前 CPU Profiler 中还不能捕获到函数名的函数(可能是匿名函数),不过仍然可以通过后面的行数去对应查看。

如何查看 ShadowNode 支持了哪些 ECMAScript 特性?

这里我们借助于一个非常有趣的库 Tokimon/es-feature-detection,具体使用方式为:

$ npm install && iotjs tools/report-esfeature.js

将会输出支持列表,支持的特性将会以绿色提示出来:

Screen Shot 2018-07-28 at 8.15.28 PM.png

小故事:20行代码优化了20%的性能

想直接看优化代码的同学可以直接跳转到 console: optimize the log function for single param by yorkie · Pull Request #140 · Rokid/ShadowNode

这件事其实发生在一个月前,我们设备端的代码刚刚移植到一款单核 CPU 的低端设备中,意外发现运行非常缓慢,当时并没有相对比较完整的 CPU Profiling 工具,只能通过日志的方式,发现在虚拟机内部存在大量的 String 对象创建,是其他对象的600倍左右。

这时,我们就去查找引擎内部的代码,慢慢定位到了 util#format 这个函数上,它内部会把大量字符串、数字、对象等都创建一个新的 String,并且还存在着递归和 while 循环,因此我想到的第一件事就是通过 String Template 来替代字符串拼接,并且针对单个参数的调用做优化,把第一个参数直接输出到 Stdio,避免了大量调用 util#format 的情况。

通过这个改动,我们把之前的 String 对象数量下降到了跟其他种类持平,同时建议上层的应用开发者使用 String Template 来替代 console.log 的多参数调用,这样整个业务代码最终的性能提升了20%。

为什么要说这个故事呢?很简单,优化真的是一件简单也不简单的事情。

要做得简单,其实往往就是通过对业务的理解,找出一些特殊且常用的路径,然后使用一种更简单优雅的方式去完成任务,而对于通用性的需求,还是使用原始的方式去做。而不简单则是在发现这些规则或者路径的时候,往往需要对业务,对 API 以及引擎都足够了解,这样才能找到最佳的路径去做出最好的优化。

一如既往的 Flag

这次的发布虽然时间上没有打脸,但 Features 上的脸都快被打没了(逃)。我其实在发布版本时一度犹豫是否要等到上次的 Flag 依依完成后,再做发布,不过想想算了,打脸就打脸,这才是开源的魅力,没做完就是要挨批评的,就算挨着批评也想要把我们过去一个月做的事情分享给大家的心情是不会变的。

好了,言归正传,我们下个版本就是 v0.10 了,在此之前,我们会集中注意力完成:

是的,ShadowNode N-API 将会是 v0.9.x 中我们唯一确保要完成的一项功能,因为这将使得 ShadowNode 更加靠近 Node.js 社区,当然也包括开发者。除此之外,我们下个月还会重点跟踪一些性能问题,比如目前我们已经发现了 EventEmitter#emit 函数作为一个很基础的部分,性能却成为了一大瓶颈等。

最后,按照老惯例,还是放一个 ShadowNode 的链接,欢迎大家 Star 和 Pull Request(目前还没有出现任何 Rokid 外部贡献者哦,希望大家踊跃玩起来!)

12 回复

厉害了,加精支持,Rokid也很好用

@i5ting 谢谢哈~

支持支持,不知大佬有没有什么边边角角的issue可以让我们修修的

@aojiaotage 边边角角的问题应该还是很多的啦,你可以在自己 mac 上跑跑看,觉得有哪些你觉得需要跟 Node.js 不统一的都可以来提 PR,还能顺便熟悉熟悉 Node.js 源代码呢~

默默去克隆一份

Rokid可不可以说英文的

调用 API 是可以的~

哇~,看起来很美好

最近的 ShadowNode 已经支持 N-API 咯~

回到顶部