Node JS 中递归程序的内存使用情况

问题描述 投票:0回答:1

我想在执行完成后一段时间再次运行一个函数。我已经编写了 3 个程序,但我不确定这些程序的内存使用情况以及哪一个是最有效的方法。

方法 1 -

async function main() {
  const random = parseInt(Math.random() * 10000000);
  const arr = new Array(random).fill(0).map((_, i) => i);

  const result = arr.reduce((acc, cur) => acc + cur, 0);
  console.log(result);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  main();
}

main();

方法 2 -

async function main() {
  const random = parseInt(Math.random() * 10000000);
  const arr = new Array(random).fill(0).map((_, i) => i);

  const result = arr.reduce((acc, cur) => acc + cur, 0);
  console.log(result);

  await new Promise((resolve) => setTimeout(resolve, 3000));
  await main();
}

main();

方法 3 -

async function main() {
  const random = parseInt(Math.random() * 10000000);
  const arr = new Array(random).fill(0).map((_, i) => i);

  const result = arr.reduce((acc, cur) => acc + cur, 0);
  console.log(result);

  await new Promise((resolve) => setTimeout(resolve, 3000));
}

const run = () => {
  main().then(() => {
    run();
  });
};

run();

我不确定哪一种是最好的方法。我认为在其他语言的情况下,内存使用量会增加,因此,这个问题与节点js事件循环特别相关,它会保留先前迭代的变量吗?

javascript node.js recursion v8
1个回答
0
投票

您自己尝试过测试吗?

由于这显然是一个简化的玩具示例,因此您不妨消除随机性,以使各个测试运行更容易进行比较。总是分配大数组。
您还可以减少间隔(例如减少到 0),这样您就不必等待很长时间才能看到长期效果。
通过这些更改,您可以在大约 10 秒内观察到哪些方法会泄漏内存(因为它们会因内存不足而崩溃),哪些不会。
(我故意不发布我自己的测试运行结果,因为我试图帮助您自助。)

除了内存泄漏之外,无限递归也是需要避免的,因为它最终会抛出

RangeError: Maximum call stack size exceeded
。这也很容易测试你自己;在这种情况下,您需要使函数体尽可能便宜(根本不进行分配)以使测试尽快运行。
(提示:至少你的方法之一遇到了这个问题。)

哪一种是最有效的方法。

首先突出的是

parseInt(Math.random()...)
。虽然在这种情况下其相对影响可以忽略不计,但这是一种相当低效的模式:它将数字转换为字符串,然后将其解析回数字。使用
Math.round()
(或
Math.trunc()
,取决于所需的行为)来提高效率。

当然,整个“分配一个数组,填充它,然后减少它”的方法也是计算数字 1..N 之和的一种超级低效的方法。作为一种有效的替代方法,请使用高斯直接公式。但这可能只是一个无用的例子,而不是你真正关心的。

对于重复执行本身:使用循环而不是递归。或者,更简单,直接使用

setTimeout(main, 3000)
(在
main
的末尾);无需等待虚拟 Promise 只是为了在函数调用之前实现延迟。

© www.soinside.com 2019 - 2024. All rights reserved.