You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何JavaScript中数组预分配比动态push性能更差?

为什么Node.js中预分配数组比push动态添加更慢?

你的测试结果和预期相反,核心原因在于V8引擎对不同数组创建方式的内部优化逻辑差异,具体可以拆解为以下几点:

  • 空洞数组的额外处理开销:new Array(size)创建的是一个空洞数组(所有元素为empty状态,并非undefined),当你逐个为元素赋值时,V8需要频繁检查元素状态,处理从empty到具体值的类型转换,甚至可能触发数组结构调整(比如从慢数组转为快数组、调整元素存储模式),这会带来额外性能损耗。而push操作是连续向数组末尾添加元素,不会产生空洞,V8可以维持数组的**Fast Elements(快数组)**状态,全程无需额外状态检查。

  • 内存初始化策略不同:new Array(size)仅分配内存空间,但并未初始化元素值;而push在添加元素时,V8会预判元素类型(此处为数字),提前优化内存布局,避免后续类型转换开销。预分配数组的赋值操作相当于在未初始化的内存区域写入数据,V8内存管理器需要做更多校验工作。

  • V8扩容机制的高效性:你可能高估了扩容开销。V8的数组扩容采用预分配冗余空间策略(通常每次扩容到当前容量的1.5-2倍),对于1亿规模的数组,push的扩容次数仅约27次(从初始容量4开始,每次翻倍至超过1亿),扩容总开销远小于处理空洞数组的额外成本。

测试验证补充

如果修改预分配方式,避免空洞数组,性能会显著提升:

  • 先填充默认值再赋值:
    let array = new Array(size).fill(0);
    
  • 使用TypedArray(固定类型数组,无空洞问题):
    let array = new Uint32Array(size);
    

这两种方式的性能会和push接近甚至更优,因为它们规避了空洞数组的处理开销。

你的测试代码

function testPush(size) {
  let start = process.hrtime.bigint();
  let array = [];
  for (let i = 0; i < size; i++) {
    array.push(i);
  }
  let end = process.hrtime.bigint();
  return Number(end - start) / 1e6; // Convert to milliseconds
}

function testPreAllocated(size) {
  let start = process.hrtime.bigint();
  let array = new Array(size);
  //   let array = new Uint32Array(size);
  //   let array = Array.from({ length: size });
  for (let i = 0; i < size; i++) {
    array[i] = i;
  }
  let end = process.hrtime.bigint();
  return Number(end - start) / 1e6; // Convert to milliseconds
}

function compareArrays() {
  const size = 1e8; // 100 million
  console.log(`Testing with array size: ${size}`);

  console.log("Starting push test...");
  let pushTime = testPush(size);
  console.log(`Push test completed in ${pushTime.toFixed(2)} ms`);

  console.log("Starting pre-allocated test...");
  let preAllocatedTime = testPreAllocated(size);
  console.log(`Pre-allocated test completed in ${preAllocatedTime.toFixed(2)} ms`);
}

compareArrays();

测试输出

Testing with array size: 100000000
Starting push test...
Push test completed in 1624.93 ms
Starting pre-allocated test...
Pre-allocated test completed in 4824.86 ms

内容的提问来源于stack exchange,提问作者Mikhael Abdallah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:42:27