6

Short question: I have a javascript that goes very deep in recursion. How can I increase the stack size so that I can execute it (something like "ulimit -s unlimited" in Unix systems)?

Long story: I have to draw a graph and I use Cytoscape JS (http://js.cytoscape.org/) coupled with the Dagre layout extension (https://github.com/cytoscape/cytoscape.js-dagre). The drawing algorithm goes deep in the recursion and I end up getting "Uncaught RangeError: Maximum call stack size exceeded" in Chrome and "too much recursion" in Firefox. How can I set the stack size to unlimited or very large (i.e. like "ulimit -s unlimited" in Unix systems) so that I can draw the graph?

Thank you!

iwicopd2
  • 87
  • 1
  • 5
  • Are you sure your algorithm is correct? Did you count the number of nested calls you had at the moment you get out of stack space? Is it a reasonable figure? – trincot Feb 13 '16 at 14:20
  • Yes, the algorithm is correct. The thing is that the graph is kind of big and the drawing algorithm goes deep in recursion. However, using other drawing algorithms (that do not use recursion), I am able to draw it fairly fast... So I am supposing that if I can increase the stack size to a reasonably large size, I will be able to draw it. I searched, but could not find any answer... In the worst case, I would need to modify Dagre algorithm to change it from recursive to iterative... But I'd like to check if are there any way of setting the stack size limit of the javascript engine of browsers. – iwicopd2 Feb 13 '16 at 14:24
  • 1
    Adding more context, here you can find the stack size limit of several browsers: http://stackoverflow.com/questions/7826992/browser-javascript-stack-size-limit?rq=1 . I just need to increase this limit. – iwicopd2 Feb 13 '16 at 14:32
  • But could you report on the number of nested calls you are at before getting out of memory? – trincot Feb 13 '16 at 14:41
  • Hello. I am using a third-party library, and several functions go deep in the recursion. One of them went for around 3000 levels, however it is impractical for me to change the whole library for this. I have a workaround for now, which involves changing the stack size of Google Chrome by invoking it with --js-flags="--stack_size x" command-line arguments, with a big x. Thank you very much for the help. – iwicopd2 Feb 16 '16 at 01:07

3 Answers3

1

Chrome has a flag for this:

chromium-browser --js-flags="--stack-size 2048"

You will also want to run ulimit -s unlimited before running the command above, though: otherwise, your deeply recursive Javascript code will crash Chrome.

Clément
  • 12,299
  • 15
  • 75
  • 115
0

Try changing your algorhythm to not use as much stack space on each iteration of the function. For instance:

  • Setting local variables to null when not being used.
  • Use global variables for temporary calculations when possible. That way, that temporary variable won't be on the stack.
  • Use fewer variables in your recursive function. Reuse the same variables for different things in different parts of the function.
  • Break your recursive function into several functions. Some of those functions won't be recursive and therefore the local variables in those functions won't carry on when the recursive function calls itself.
  • Create a global array of things to do and add items to this list instead of calling a function recursively. use the push and pop methods of the array() object.
  • Have fewer parameters on your recursive function. Pass an object instead.

I hope these ideas help you.

Russell Hankins
  • 1,196
  • 9
  • 17
  • Hello. Thank you for the answer. I have thought about some of these things, but your list is indeed more complete! However, what if I did all possible to minimize the stack space at each function call, but the algorithm itself goes too deep in the recursion and I can't change to a iterative algorithm? I.e. I really need to increase the stack size? I just can't do this in modern browsers? Should I thus recode my script as a desktop application to be able to have a big stack size? – iwicopd2 Feb 13 '16 at 14:43
  • I was programming once in C in Windows and had a very large binary tree. I wrote a recursive function to delete the tree once the function finished. The recursive function would crash. I had to rewrite the recursive function to an iterative function. I don't think changing languages or expanding the stack will fix your algorithm issue. If you double the stack size or triple the stack size, you'd probably still have the same problem. – Russell Hankins Feb 13 '16 at 14:49
  • Hello. I am using a third-party library, and several functions go deep in the recursion. It is impractical for me to change the whole library for this. I also agree and prefer to write code iteratively than recursively, but sometimes recursion is just way more clean algorithmically. In UNIX systems, sometimes we have this and a ulimit -s unlimited solves the problem. I have a workaround for now for js, which involves changing the stack size of Google Chrome by invoking it with --js-flags="--stack_size x" command-line arguments, with a big x. Thank you very much for the help. – iwicopd2 Feb 16 '16 at 01:09
  • It would be a good idea to post a Github issue in the dagre repo, as that is where the recursion is happening: https://github.com/cpettitt/dagre – maxkfranz Feb 16 '16 at 16:23
-1

You cannot alter the stack size in browsers, but you can use a trick called trampolining.

You can find a working code solution here:

How to understand trampoline in JavaScript?

Erik Kaplun
  • 37,128
  • 15
  • 99
  • 111
  • The question was "How can I set the stack size to unlimited or very large?" This does not answer the question. – Clément Apr 01 '18 at 18:18
  • @Clément ...even though it has been selected as the accepted answer?? :O the answer implies that it is impossible, just doesn't explicitly state it. – Erik Kaplun Nov 01 '19 at 09:16
  • Thanks for the edit. Are you sure it's actually impossible? The flag that the OP mentioned in the comments does seem increase the stack size (that effect isn't achievable from javascript, but it still works from the command line). – Clément Nov 04 '19 at 14:13