为何Bun执行矩阵乘法代码耗时是Node.js的两倍?
为何Bun在矩阵乘法测试中比Node.js慢两倍?
我测试了Bun和Node.js的矩阵乘法性能,原本以为Bun会大幅领先,但实际结果是Bun耗时是Node.js的两倍。
测试代码如下:
// 矩阵乘法测试 function multiplyMatrices(matrixA, matrixB) { const result = []; for (let i = 0; i < matrixA.length; i++) { result[i] = []; for (let j = 0; j < matrixB[0].length; j++) { let sum = 0; for (let k = 0; k < matrixA[0].length; k++) { sum += matrixA[i][k] * matrixB[k][j]; } result[i][j] = sum; } } return result; } // 生成矩阵并执行乘法 const matrixSize = 2000; const matrixA = Array.from({ length: matrixSize }, () => Array(matrixSize).fill(1)); const matrixB = Array.from({ length: matrixSize }, () => Array(matrixSize).fill(1)); console.time("Matrix Multiplication"); multiplyMatrices(matrixA, matrixB); console.timeEnd("Matrix Multiplication");
测试结果:
% node node.js Matrix Multiplication: 22.287s % bun node.js [47.58s] Matrix Multiplication
核心原因:JS引擎优化侧重点差异
Bun基于JavaScriptCore(JSC)引擎,Node.js使用V8引擎,两者在CPU密集型同步代码的优化策略上存在明显区别:
- V8的TurboFan编译器:在嵌套循环、数组连续访问这类场景下的优化更成熟,比如自动循环展开、缓存预取、内存访问模式优化,能大幅提升三重循环的执行效率。
- JSC的B3/FTL编译器:虽然JSC在很多IO密集型、前端场景下性能优异,但当前版本在大规模嵌套循环的纯CPU密集任务上,优化策略不如V8激进,导致执行效率偏低。
次要因素:内存访问的缓存命中率问题
你的代码中访问matrixB[k][j]属于列优先访问,但JS数组是按行存储的,这种跨列访问会频繁跳过内存块,导致CPU缓存命中率极低。V8可能针对这种场景做了自动的内存布局优化或循环重排,而JSC没有类似的优化,进一步放大了性能差距。
验证与优化建议
调整循环顺序:交换j和k的循环,改成按行优先访问
matrixB,提升缓存命中率:function multiplyMatricesOptimized(matrixA, matrixB) { const result = []; const n = matrixA.length; const m = matrixB[0].length; const p = matrixA[0].length; for (let i = 0; i < n; i++) { result[i] = []; const rowA = matrixA[i]; for (let k = 0; k < p; k++) { const valA = rowA[k]; const rowB = matrixB[k]; for (let j = 0; j < m; j++) { result[i][j] = (result[i][j] || 0) + valA * rowB[j]; } } } return result; }这种调整能显著提升两者的性能,同时缩小Bun和Node.js的差距。
使用TypedArray:用
Float64Array代替普通数组,TypedArray的内存布局更紧凑连续,引擎更容易做底层优化:const matrixA = new Float64Array(matrixSize * matrixSize).fill(1); // 访问时通过 index = i * matrixSize + k 定位元素升级Bun版本:Bun迭代速度很快,后续版本可能会针对JSC的这类场景做专项优化,测试最新版Bun可能会有性能改善。
内容的提问来源于stack exchange,提问作者seongkuk han
相关产品推荐
相关产品推荐

