Node.js切片字符串内存

时间:2019-05-14 02:27:04

标签: node.js string garbage-collection

我是trying

r = [];
for (i = 0; i < 1e3; i++) {
    a = (i+'').repeat(1e6);
    r[i] = a.slice(64, 128);
}

,并且内存不足。从here中我们看到是因为所有a都保存在GC的cuz中,而其中的一部分被使用了。

  1. 如何使slice不保留内存?我尝试了r[i]=''+a.slice(64, 128)+'',但仍然是OOM。我是否必须a[64]+...+a[127](循环也算作蛮力)?
  2. 切片并仅保留旧的大字符串的必要部分难吗? problem here仅提到“将每个子字符串复制为新字符串”,但没有提及“释放部分字符串,剩下可评估的必要部分”

1 个答案:

答案 0 :(得分:0)

  1. 在这种情况下,让应用程序代码更加了解系统约束是有意义的:
const r = [];
for (let i = 0; i < 1e3; ++i) {
  const unitStr = String(i);
  // choose something other than "1e6" here:
  const maxRepeats = Math.ceil(128 / unitStr.length); // limit the size of the new string
  // only using the last 64 characters...
  r[i] = unitStr.repeat(maxRepeats).slice(64, 128);
}

...应用程序改进是:当每个输出字符串只需要 64 个字节时,不再构造 1000 个字符串,每个字符串最多 3,000,000 个字节。

  1. 未指定您的硬件和其他限制条件,但有时允许程序更多内存是合适的:
node --max-old-space-size=8192 my-script.js
  1. 一种分析方法。使用逻辑更精确地确定每个工作数据块所需的内存状态。使用提供的约束,最大限度地减少不需要的内存字符串数据的生成。
const r = new Array(1e3).fill().map((e,i) => outputRepeats(i));

function outputRepeats(idx) {
  const OUTPUT_LENGTH = 128 - 64;
  const unitStr = String(idx); // eg, '1', '40' or '286'

  // determine from which character to start output from "unitStr"
  const startIdxWithinUnit = (64 + 1) % unitStr.length;  // this can be further optimized for known ranges of the "idx" input

  // determine the approximate output string (may consume additional in-memory bytes: up to unitStr.length - 1)
  // this can be logically simplified by unconditionally using a few more bytes of memory and eliminating the second arithmetic term
  const maxOutputWindowStr = unitStr.repeat(Math.ceil(OUTPUT_LENGTH / unitStr.length) + Math.floor(Math.sign(startIdxWithinUnit)));

  // return the exact resulting string
  return maxOutputWindowStr.slice(startIdxWithinUnit, OUTPUT_LENGTH);
}