Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stack vs. Heap in Javascript? (Maximum call stack size exceeded)

I'm trying to build a web-page for which I need to shovel around several 100MB of data in JavaScript. With different browsers I run into "maximum call stack size exceeded" errors at different data amounts.

Can I fix this issue by going through my code and trying to move local variables inside functions into a more global scope to try to get them to be allocated on the heap instead of the stack? Or do these concepts not exist in JavaScript? (As far as I know, I don't have any major recursive loops in my data, so it really is a couple of huge strings / number arrays that seem to be causing the error)

If this isn't possible, are there ways to ask the browser to reserve more memory?

like image 820
Markus A. Avatar asked Jun 25 '12 16:06

Markus A.


People also ask

How do I fix maximum call stack size exceeded?

The call stack is limited in size, and when it's exceeded, the RangeError is thrown. This can happen when a deeply nested function is called, or when a lot of new variables are created. The most common way to fix this error is to reduce the number of function calls, or to limit the number of variables that are created.

How do I fix maximum call stack size exceeded see JavaScript console for details?

The "RangeError: Maximum call stack size exceeded" error occurs when a function is called so many times that the invocations exceed the call stack limit. To solve the error, specify a base case that has to be met to exit the recursion.

What is the maximum call stack size in JavaScript?

The consequences of applying a function with too many arguments (think more than tens of thousands of arguments) vary across engines (JavaScriptCore has hard-coded argument limit of 65536), because the limit (indeed even the nature of any excessively-large-stack behavior) is unspecified.

What causes maximum call stack size exceeded?

The JavaScript RangeError: Maximum call stack size exceeded is an error that occurs when there are too many function calls, or if a function is missing a base case.


1 Answers

OK, figured out the problem. There really was no recursion in my code. It is indeed possible to call JavaScript functions with hundreds of arguments if they are "varargs" functions like for example <array>.splice(...), which was my offender.

Aside: GWT implements the Java function System.arraycopy(...) using the JavaScript splice function in a more-or-less clever way.

splice accepts an arbitrary number of input elements to insert into the target array. It is possible to pass these input elements from another array by using the following construct:

var arguments = [index, howmany].concat(elements); Arrays.prototype.splice.apply(targetarray, arguments); 

This is equivalent to calling:

targetarray.splice(index, howmany, elements[0], elements[1], elements[2], ...); 

If elements gets big (see below for what "big" means for different browsers), you can get a "Maximum call stack size exceeded" error without recursion as the contents of it will be loaded onto the stack for the function call.

Here's a short script that demonstrates this issue:

var elements = new Array(); for (i=0; i<126000; i++) elements[i] = 1; try {     var arguments = [0, 0].concat(elements);     Array.prototype.splice.apply(elements, arguments);     alert("OK"); } catch (err) {     alert(err.message); } 

Using this script, "big" means the following:

  • Chrome 19: elements contains ~ 125,000 numbers
  • Safari 5.1 (on Windows): elements contains ~ 65,000 numbers
  • Firefox 12: elements contains ~ 500,000 numbers
  • Opera 11.61: elements contains ~ 1,000,000 numbers

And the winner is: Internet Explorer 8 for a change! It can use up all system memory, before this function call fails.

A side note: Firefox and Opera actually throw a different (more useful) error message: Function.prototype.apply: argArray is too large

like image 178
Markus A. Avatar answered Sep 17 '22 21:09

Markus A.