Tengo un pequeño bucle de código que arroja Uncaught RangeError: Invalid Array Length
Pude reproducirlo solo con esto en la consola de Google Chrome
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}`);Aquí está el resultado en la consola del desarrollador
Hasta donde yo sé, el tamaño máximo de matriz en Javascript es 2^32-1. Debe haber suficiente memoria para asignar aquí y el índice i nunca es negativo o está fuera de los límites de la matriz, por lo que puedo ver.
Curiosamente, si uso este código, no se bloquea
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}`);El valor asignado a yValues[i] nunca sale del rango -1, +1, por lo que tampoco puedo ver esto como un problema de número fuera de rango.
¿Alguien arroja algo de luz sobre esto?
EDITAR: Actualizar
Otro escenario que no funciona. Cálculo de un paseo aleatorio.
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; }¡Este también tira! Pero
yValues[i] = iestá bien ¯\_(ツ)_/¯
EDITAR: Actualización 2
Ahora puedo confirmar que esto es específico del navegador, si ejecuta la misma prueba en Firefox, funciona, pero el navegador le pide que espere.
¿Sospecha que la excepción Uncaught RangeError es un tiempo de espera mal informado?
La verdadera razón está en la optimización de la memoria V8. Cuando almacena números enteros, almacena el número de 32 bits en su lugar, pero cuando almacena números dobles, se almacena de manera diferente (como un objeto), por lo que la matriz yValues contiene la referencia pero el valor real almacenado en el montón. Entonces, en su ejemplo, acaba de usar toda la memoria del montón. Para ver el límite, usa: console.memory y verás algo como esto:
MemoryInfo { totalJSHeapSize: 10000000, usedJSHeapSize: 10000000, jsHeapSizeLimit: 3760000000} En mi navegador es 3_760_000_000
El objeto en el montón ocupa más de 50 bytes, por lo que mi límite ronda los 69_000_000 números de punto flotante.