5

I am currently working on some scientific calculations for which my base calculation loops are executed over and over again with recursive calls as long as at least one parameter is false.

Currently my nodejs server stops at around 905 - 915th recursive function call.

The weird thing is, that it doesn't crash, nor output any error. It just stops doing anything -> no more logs etc.

Is this some protection behaviour from node to avoid overflow?

I am struggling with this for a few weeks now whilst trying to limit the "loops" with an as intelligent as possible software.

Thank you for your help & advice. Greetings Noa.

As requested I provide some abstraction of my actual code

I hope this helps. I cannot put my original code on here because it consists of more than 1.5k lines - theres a lot to check. But the below example covers the base logic behind the recursive call.

// 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
}
noa-dev
  • 3,561
  • 9
  • 34
  • 72
  • 1
    Node makes it relatively simple to replace recursive calls with asynchronous calls and avoid stack growth altogether. Provide more details and sample code... – Amit Mar 20 '16 at 19:26
  • I rather doubt we can help you without seeing the code. Stack overflow does really well with questions that contain real code and not so well with conceptual questions with no code. – jfriend00 Mar 20 '16 at 19:29
  • I have updated my Question – noa-dev Mar 20 '16 at 19:51

2 Answers2

5

Since your code isn't complete it's hard to say exactly what's going wrong. If you exceed node's call stack limit you will get an exception, although 1000 recursions isn't normally a problem.

It might be that you're choking the Node.js event-loop. Instead of directly calling the recursive function, you can try to call

process.nextTick(function(){calculate()})
Rudolf Meijering
  • 1,559
  • 1
  • 14
  • 20
  • Thank you I will try that method today! – noa-dev Mar 25 '16 at 10:44
  • It doesn't stop the function execution any more but ends in an endless loop - which might be the reason why the default function call got stopped after a few loops without any different pattern. – noa-dev Mar 25 '16 at 23:15
1

It's not suprised that direct recursive call will result in stack overflow, however, it seems that frequent function calls will get node hang up(BTW, I don't know why this happens :( ).

For example, the following script get frozen at around 4k ~ 5k loops on my machine with 1.6 GHz CPU and 3.3 GiB memory, and node keeps swallowing my available memory after that.

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

But if I changed process.nextTick(cal); to setTimeout(cal, 0);, everything works fine.

So as for your question, I think you can use something like setTimeout(calculate, 100) in your script to prevent recursive call and defer it slightly.

knight42
  • 910
  • 10
  • 15
  • The process.nextTick did it for me. Although I end up in an endless loop now - but that might be a programming error on my end. :) – noa-dev Mar 27 '16 at 19:10