这几天 javascript 最火的新闻莫过于 koa2 发布了正式版。目前最新版本是v2.0.1,koa2 团队宣称 “只要 nodejs 还未支持 async,koa2 就一直不发布正式版”,随着 node v7.6.0 的到来,全栈工程师们期待已久的 koa2 也终于正式版了——完美支持 async 函数,优雅的解决异步回调。
这一切的功劳还要归功于 V8 引擎。知乎上关于 async 的问题又重新出现在了 timeline 上:ES next中async/await proposal实现原理是什么?我看到很多人在回答 async 本职是 promise、yield、generator,于是也凑热闹回答了一下,等晚上再看的时候,顿时有一种穿越感:
很早之前 V8 就已经更换了新的优化执行引擎:TurboFan,不仅仅可以优化 try/catch/finally、for...of 等之前 Crankshaft 不能优化的语法,还支持了更多的 ES2015+ features。
TurboFan 引擎不仅仅是增加了对 async 的支持,更增加了对 async、generators 优化的支持。下面是生成的二进制码和 TurboFan 执行图:
在此之前很多需要借助 babel 编译的 ES2015 新特性都得到了原生支持。
异步函数:
async function* readLines(path) {
let file = await fileOpen(path);
try {
while (!file.EOF) {
yield await file.readLine();
}
} finally {
await file.close();
}
}
上面的 187 个字符会被 babel 编译成 2987 个字符,代码大小增加了 650%。文件地址:https://gist.github.com/justjavac/cdfe4cc0a55744e093250b8aca6a325a
对于数组和对象的析构赋值(array destructuring)
function fn() {
var [c] = data;
return c;
}
bable 编译成:
"use strict";
var _slicedToArray = function () {...(此处省略630个字符)
function fn() {
var _data = data,
_data2 = _slicedToArray(_data, 1),
c = _data2[0];
return c;
}
查看完整代码会发现里面有 Crankshaft 无法优化的 try/catch/finally。而在最新 V8 里面,析构赋值几乎和数组元素直接赋值一样快:
function fn() {
var c = data[0];
return c;
}
其它的 ES2015+ 特性也有大幅度优化:
关注最新的 V8 引擎进展可以看看 V8 的 《ES2015 and beyond performance plan(需科学上网)》。
参考文章:
- High-performance ES2015 and beyond
- Async Iterators for JavaScript
- V8’s new interpreter and compiler pipeline
- ES2015 and beyond performance plan
最后是广告时间,欢迎订阅我的公众号: