【问题标题】:NodeJS: invalid array length Allocation failed - JavaScript heap out of memoryNodeJS:无效的数组长度分配失败 - JavaScript 堆内存不足
【发布时间】:2021-01-04 07:54:52
【问题描述】:

我正在尝试从文件中导出数据并使用 ExcelJS 将此数据添加到 Excel 文件中。

worksheet.addRows(freedomRawData.records);

'records' 是一个包含超过 165,000 个元素的数组。将数据写入 excel 文件时,出现错误 -

致命错误:无效数组长度分配失败 - JavaScript 堆内存不足

相同的脚本适用于“记录”长度为 115,000 个元素的数据。通过互联网,我找到了以下方法:

node --max-old-space-size=8192 <file_name>.js

这不起作用,我尝试使用 RAM 的最大容量 (16384MB);这也没有帮助。我是 NodeJS 的新手,任何帮助将不胜感激。

【问题讨论】:

  • 目标只是将电子表格写入磁盘吗?如果是这样,请阅读 docco 的streaming section。写入/提交到流然后不会首先在内存中构建整个电子表格
  • 是的,我们的目标是创建一个新文件后对数据执行某些计算。感谢上面的链接;我会通读一遍。

标签: javascript node.js puppeteer heap-memory exceljs


【解决方案1】:

ExcelJS 有一个流式编写器接口:

async function writeExcel(rows_array){
  const workbook = new Excel.stream.xlsx.WorkbookWriter({ filename: 'stream.xlsx' })
  const worksheet = workbook.addWorksheet('data')
  for (const row of rows_array) {
    worksheet.addRow(row).commit()
  }
  await workbook.commit()
}

在这种情况下,由于 node/v8 垃圾收集器的工作方式,数据集仍可能存在内存问题。垃圾收集需要点击事件循环才能真正清理“释放”的内存。如果您运行了足够多的同步代码,例如 for 循环,并且该循环每次迭代分配更多内存,那么 GC 将无法运行,直到代码暂停之后(即最终的 worbook.commit()。如果您仍然遇到OOM 问题,然后您可以强制异步暂停以允许在实际收集 .commit() 之后可以清理的行内存。

  for (const i in rows_array) {
    worksheet.addRow(rows_array[i]).commit()
    if (i % 10000 === 0) await Promise.resolve(true)
  }

【讨论】:

  • 工作得很好。谢谢,@马特。我想知道为什么它在第一次运行时不起作用;直到我意识到第一个答案await workbook.commit() 中有错字:)
  • 拯救了我的一天!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
  • 2020-03-20
  • 2020-06-25
  • 2018-12-05
  • 2018-09-25
  • 2019-05-05
  • 1970-01-01
相关资源
最近更新 更多