SWC 與 Babel 的效能比較
JavaScript 是單執行緒的。JS 執行緒不適合進行大量運算。讓我們來談談 babel
和 swc
,它們都是運算密集型的。
同步基準
讓我們對單核心工作負載進行基準測試。請注意,這使用 transformSync
,這在實際應用中很少見。
[transform]
swc (es3) x 616 ops/sec ±4.36% (88 runs sampled)
swc (es2015) x 677 ops/sec ±2.01% (90 runs sampled)
swc (es2016) x 1,963 ops/sec ±0.45% (93 runs sampled)
swc (es2017) x 1,971 ops/sec ±0.35% (94 runs sampled)
swc (es2018) x 2,555 ops/sec ±0.35% (93 runs sampled)
swc-optimize (es3) x 645 ops/sec ±0.40% (90 runs sampled)
babel (es5) x 34.05 ops/sec ±1.15% (58 runs sampled)
SWC 非常快。儘管 swc (es3)
的工作量比 babel (es5)
多,但 swc (es3)
比 babel (es5)
快。
實際基準
transformSync
和 transformFileSync
在實際應用中很少使用,因為它會封鎖目前的執行緒。 await Promise.all()
經常使用,而且比下列方法更好
for (const promise of promises) {
await promise;
}
讓我們使用 Promise.all()
為實際的實際使用建立基準測試。
理想情況
首先,我建立了理想情況的基準。它一次呼叫 [n]
個 Promise,其中 n
是實體 CPU 核心數。請參閱 node-swc 儲存庫(在新分頁中開啟) 以取得完整程式碼。
const os = require("os");
const cpuCount = os.cpus().length;
const SOURCE = `
// See the link above
`;
const SUITES = [
// ...
// See the link above
];
const arr = [];
for (let i = 0; i < cpuCount / 2; i++) {
arr.push(0);
}
console.info(`CPU Core: ${cpuCount}; Parallelism: ${arr.length}`);
console.info(
`Note that output of this benchmark should be multiplied by ${arr.length} as this test uses Promise.all`
);
SUITES.map(args => {
const [name, requirePath, fn] = args;
const func = fn.bind(null, require(requirePath));
bench(name, async done => {
await Promise.all(arr.map(v => func()));
done();
});
});
我在舊桌上型電腦上執行基準測試。它有 E3-v1275 和 24GB RAM。以下輸出從基準測試輸出中照樣複製。
CPU Core: 8; Parallelism: 4
Note that output of this benchmark should be multiplied by 4 as this test uses Promise.all
[multicore]
swc (es3) x 426 ops/sec ±3.75% (73 runs sampled)
swc (es2015) x 422 ops/sec ±3.57% (74 runs sampled)
swc (es2016) x 987 ops/sec ±2.53% (75 runs sampled)
swc (es2017) x 987 ops/sec ±3.44% (75 runs sampled)
swc (es2018) x 1,221 ops/sec ±2.46% (77 runs sampled)
swc-optimize (es3) x 429 ops/sec ±1.94% (82 runs sampled)
babel (es5) x 6.82 ops/sec ±17.18% (40 runs sampled)
現在,我們需要將它乘以 4,因為我們每次反覆執行 4 個操作。
swc (es3) x 1704 ops/sec ±3.75% (73 runs sampled)
swc (es2015) x 1688 ops/sec ±3.57% (74 runs sampled)
swc (es2016) x 3948 ops/sec ±2.53% (75 runs sampled)
swc (es2017) x 3948 ops/sec ±3.44% (75 runs sampled)
swc (es2018) x 4884 ops/sec ±2.46% (77 runs sampled)
swc-optimize (es3) x 1716 ops/sec ±1.94% (82 runs sampled)
babel (es5) x 27.28 ops/sec ±17.18% (40 runs sampled)
這是實際結果。
babel (es5)
的效能下降了。非同步並非免費。儘管如此,34.05 ops/sec
=> 27.28 ops/sec
比我預期的要好得多。
大量操作的基準測試
我稍微修改了基準測試檔案,讓它每次反覆執行建立 100 個 Promise。
CPU Core: 8; Parallelism: 100
Note that output of this benchmark should be multiplied by 100 as this test uses Promise.all
[multicore]
swc (es3) x 21.99 ops/sec ±1.83% (54 runs sampled)
swc (es2015) x 19.11 ops/sec ±3.39% (48 runs sampled)
swc (es2016) x 55.80 ops/sec ±6.97% (71 runs sampled)
swc (es2017) x 62.59 ops/sec ±2.12% (74 runs sampled)
swc (es2018) x 81.08 ops/sec ±5.22% (75 runs sampled)
swc-optimize (es3) x 18.60 ops/sec ±2.13% (50 runs sampled)
babel (es5) x 0.32 ops/sec ±19.10% (6 runs sampled)
它必須像上面一樣乘以 100。
swc (es3) x 2199 ops/sec ±1.83% (54 runs sampled)
swc (es2015) x 1911 ops/sec ±3.39% (48 runs sampled)
swc (es2016) x 5580 ops/sec ±6.97% (71 runs sampled)
swc (es2017) x 6259 ops/sec ±2.12% (74 runs sampled)
swc (es2018) x 8108 ops/sec ±5.22% (75 runs sampled)
swc-optimize (es3) x 1860 ops/sec ±2.13% (50 runs sampled)
babel (es5) x 32 ops/sec ±19.10% (6 runs sampled)
為什麼 SWC 的效能沒有大幅下降?關鍵在於 Node.js。Node.js 內部管理工作執行緒池,而 SWC 在其上執行。因此,即使您一次建立 100 個 Promise,工作執行緒的數量也遠小於它。
結論
名稱 | 1 個核心,同步 | 4 個 Promise | 100 個 Promise |
---|---|---|---|
swc (es3) | 616 ops/秒 | 1704 ops/秒 | 2199 ops/秒 |
swc (es2015) | 677 ops/秒 | 1688 ops/秒 | 1911 ops/秒 |
swc (es2016) | 1963 ops/秒 | 3948 op s/秒 | 5580 ops/秒 |
swc (es2017) | 1971 ops/秒 | 3948 ops/秒 | 6259 ops/秒 |
swc (es2018) | 2555 ops/秒 | 4884 ops/秒 | 8108 ops/秒 |
swc-optimize (es3) | 645 ops/秒 | 1716 ops/秒 | 1860 ops/秒 |
babel (es5) | 34.05 ops/秒 | 27.28 ops/秒 | 32 ops/秒 |
swc
擴充性良好,因為它幾乎所有的工作都在工作執行緒中完成。根據 100 個 Promise
的處理量優於 4 個 Promise
的事實,我們可以得出結論,Node.js 的工作執行緒池會利用超執行緒。
swc
會隨著 CPU 核心數目擴充。 Promise.all
足以進行擴充。