Home > Software design >  JavaScript pre-allocated array Uncaught RangeError: Invalid Array Length
JavaScript pre-allocated array Uncaught RangeError: Invalid Array Length

Time:12-03

I have a small loop of code which is throwing Uncaught RangeError: Invalid Array Length

I was able to reproduce it with just this in the Google Chrome console

const COUNT = 100_000_000;
const xValues = new Array(COUNT);
const yValues = new Array(COUNT);
for (let i = 0; i < COUNT; i  ) {
    xValues[i] = i;
    yValues[i] = Math.sin(i * 0.000001);
}
console.log(`count: ${yValues.length}`);

Here's the output in developer console

enter image description here

As far as I know the maximum array size in Javascript is 2^32-1? There should be enough memory to allocate here and the index i is never negative or outside the bounds of the array as far as I can see.

Curiously enough, if I use this code, there is no crash

const COUNT = 100_000_000;
const xValues = new Array(COUNT);
const yValues = new Array(COUNT);
for (let i = 0; i < COUNT; i  ) {
    xValues[i] = i;
    yValues[i] = i;
}
console.log(`count: ${yValues.length}`);

enter image description here

The value assigned to yValues[i] never goes outiside of the range -1, 1 so I can't see this as a number out of range problem either.

Anyone shed any light on this?

EDIT: Update

Another scenario that doesn't work. Computing a random walk.

    const count = 100_000_000;
    const xValues = new Array(COUNT);
    const yValues = new Array(COUNT);
    let prevYValue = 0;
    for (let i = 0; i < COUNT; i  ) {
        const curYValue = Math.random() - .5;

        xValues[i] = i;
        yValues[i] = prevYValue   curYValue;

        prevYValue  = curYValue;
    }

This one throws as well! But

    yValues[i] = i 

is fine ¯\_(ツ)_/¯

EDIT: Update 2

Can now confirm this is browser specific, if you run the same test in firefox it works, but the browser asks you to wait.

Suspect the exception Uncaught RangeError is a badly reported timeout?

CodePudding user response:

The real reason is in V8 memory optimization. When you store integers - it stores the 32 bit number in place, But when you store double-number - it is stored differently (as an object) - so yValues array contains the reference but the actual value stored in heap. So in your example you just used all heap memory. To see the limit, use: console.memory and you'll see something like this:

MemoryInfo {
totalJSHeapSize: 10000000, 
usedJSHeapSize: 10000000, 
jsHeapSizeLimit: 3760000000}

In my browser it is 3_760_000_000

The object on heap takes 50 bytes, so my limit somewhere around 69_000_000 floating point numbers.

  • Related