這幾天 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%。檔案地址:gist.github.com/justjavac/c…
對於陣列和物件的析構賦值(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
最後是廣告時間,歡迎訂閱我的公眾號: