【问题标题】:Limited function calls in nodejs on same operation?同一操作中nodejs中的有限函数调用?
【发布时间】:2016-07-07 05:07:14
【问题描述】:

我目前正在研究一些科学计算,只要至少一个参数为假,我的基本计算循环就会通过递归调用一遍又一遍地执行。

目前我的 nodejs 服务器在第 905 - 915 个递归函数调用附近停止。

奇怪的是,它不会崩溃,也不会输出任何错误。它只是停止做任何事情 -> 不再有日志等。

这是节点避免溢出的某种保护行为吗?

我已经为此苦苦挣扎了几个星期,同时尝试使用尽可能智能的软件来限制“循环”。

感谢您的帮助和建议。 问候诺亚。

根据要求,我提供了一些实际代码的抽象

我希望这会有所帮助。我不能把我的原始代码放在这里,因为它包含超过 1.5k 行 - 有很多要检查的地方。 但下面的示例涵盖了递归调用背后的基本逻辑。

// Contains objects which contain an array
// which represents the amount of the ex_obj terms
var amount = {
  a:[10,10],
  b:[7.5,7.5],
  c:[2.5,2.5,2.5,2.5]
}

// Contains objects, which contain an array of other objects
// that represent some selection
// Each object in an array consists of different values per attribute per 1 amount
var ex_obj = {
  a: [
    {aa: 1.41, ab: 0.143, ac: 0.5},
    {aa: 1.30, ab: 1.43, ac: 0.42}
  ],
  b: [
    {aa: 0.32, ab: 5.54, ac: 1.3},
    {aa: 0.33, ab: 4.49, ac: 2.5}
  ],
  c: [
    {aa: 0.54, ab: 1.4, ac: 3.5},
    {aa: 0.39, ab: 1.434, ac: 3.91},
    {aa: 0.231, ab: 1.44324, ac: 2.91},
    {aa: 0.659, ab: 1.554, ac: 3.9124},
  ]
}

// Here we have an object that represents
// the "to be" state which should be achieved
var should_be ={
  aa: 14.534,
  ab: 3.43,
  ac: 5.534
}

function calculate(){
  // Now we want to mulitply the amount object values with
  // the ex_obj values

  for(let prop in ex_obj){
    for(let i = 0, i < ex_obj[prop].length, i++){
      for(let propa in ex_obj[prop][i]){
        // here every aa,ab,ac gets mulitplied with the
        // contains of the amount obj for the matching
        // propertyname
      }
    }
  }

  // the next step is to check if the sum of all ex_obj property
  // child values per aa, ab and ac match the should_be propertie values

  // if everything is above the should_be and not too high then the
  // programm can stop here and print out the amount obj.

  // if the sum of the ex_obj properties is too little
  // compared to the should_be obj
  // we need to check which property is too little
  // e.g. aa is too little
  // then we check where aa in the ex_obj per 1 value is
  // the highest
  // then we increment the matching amount property child
  // and start calculate() again

  // same procedure for - if something is too much
}

【问题讨论】:

  • Node 使得用异步调用替换递归调用变得相对简单,并且完全避免了堆栈增长。提供更多细节和示例代码...
  • 我很怀疑我们可以在不查看代码的情况下为您提供帮助。堆栈溢出对于包含真实代码的问题非常有效,而对于没有代码的概念性问题则不太好。
  • 我已经更新了我的问题

标签: node.js recursion recursive-datastructures


【解决方案1】:

由于您的代码不完整,因此很难确切地说出了什么问题。如果超过节点的调用堆栈限制,您将收到异常,尽管 1000 次递归通常不是问题。

可能是您阻塞了 Node.js 事件循环。而不是直接调用递归函数,可以尝试调用

process.nextTick(function(){calculate()})

【讨论】:

  • 谢谢,我今天就试试那个方法!
  • 它不再停止函数执行,而是以无限循环结束——这可能是默认函数调用在几个循环后停止而没有任何不同模式的原因。
【解决方案2】:

直接递归调用会导致堆栈溢出并不奇怪,但是,频繁的函数调用似乎会导致节点挂起(顺便说一句,我不知道为什么会发生这种情况:()。

例如,以下脚本在我的具有 1.6 GHz CPU 和 3.3 GiB 内存的机器上冻结在大约 4k ~ 5k 循环,之后节点不断吞噬我的可用内存。

var i = 0;
function cal() {
   console.log(++i);
   process.nextTick(cal);
}
cal();

但如果我将process.nextTick(cal); 更改为setTimeout(cal, 0);,一切正常。

至于你的问题,我认为你可以在你的脚本中使用类似setTimeout(calculate, 100) 的东西来防止递归调用并稍微推迟它。

【讨论】:

  • process.nextTick 为我做了。尽管我现在陷入了无限循环——但这可能是我的编程错误。 :)
猜你喜欢
  • 1970-01-01
  • 2020-04-25
  • 2017-06-08
  • 2019-09-10
  • 2018-05-18
  • 1970-01-01
  • 2021-10-09
  • 2021-02-23
  • 2018-10-28
相关资源
最近更新 更多