Estoy comparando un código javascript simple y veo un uso de memoria inesperado en el siguiente ejemplo:
function startTimer() { const time = process.hrtime(); return time; } function endTimer(time) { function roundTo(decimalPlaces, numberToRound) { return +(Math.round(numberToRound + `e+${decimalPlaces}`) + `e-${decimalPlaces}`); } const diff = process.hrtime(time); const NS_PER_SEC = 1e9; const result = (diff[0] * NS_PER_SEC + diff[1]); // Result in Nanoseconds const elapsed = result * 0.0000010; return roundTo(6, elapsed); // Result in milliseconds } SIZE = 10000000 start = startTimer() let a = Array(SIZE).fill(1) elapsed = endTimer(start) const proc = process.memoryUsage() console.log("rss (MB): ", proc.rss/1000/1000) console.log("heapTotal (MB): ", proc.heapTotal/1000/1000) console.log("heapUsed (MB): ", proc.heapUsed/1000/1000) console.log("elapsed (ms): ", elapsed)Cuando TAMAÑO = 10 MB obtengo:
[ThinkPad-E14-Gen-2:/home/jj/Documents/repos/tests_javascript]% node --max-old-space-size=4192 example.js SIZE (MB): 10 rss (MB): 113.87 heapTotal (MB): 84.19 heapUsed (MB): 83.29 elapsed (ms): 47.44Cuando TAMAÑO = 100 MB obtengo 66 veces más memoria rss y 500 veces más tiempo de ejecución:
[ThinkPad-E14-Gen-2:/home/jj/Documents/repos/tests_javascript]% node --max-old-space-size=4192 example.js SIZE (MB): 100 rss (MB): 7529.71 heapTotal (MB): 4083.26 heapUsed (MB): 4008.59 elapsed (ms): 23135.14¿Por qué está pasando esto? ¿Cómo hago para evaluar comparativamente adónde van las asignaciones de tiempo/memoria?
Puede encontrar esto útil:
La penalización de rendimiento puede deberse al tipo de matriz perforada producida por el constructor Array(SIZE) .
Después de leer los artículos anteriores, puede resultarle interesante comparar la diferencia en memoria y tiempo entre llenar matrices de 10_000_00 y (digamos) 50_000_000 de esta manera:
let a = Array(SIZE).fill(1) let a = Array.from({ length: SIZE }).fill(1) let a = [1]; for (let i = 0; i < SIZE; i++) a.push(1); let a = [1]; for (let i = 0; i < SIZE; i++) a[i] = 1; let a = new Uint8Array(SIZE).fill(1) // Wow!El motor Javascript optimiza el uso repetido de funciones. De todos modos, aquí hay otra forma de hacerlo (no lo suficientemente rápido pero prueba la parte del compilador/optimizador justo a tiempo):
Intente producir la matriz completa solo una vez, luego utilícela, luego use JSON.parse en la cadena cuando lo necesite.
let n=1000; let arr=[]; for(let i=0;i<n;i++) arr.push(1); const constant=JSON.stringify(arr); for(let i=0; i<10;i++){ let t = Date.now(); let newArr = JSON.parse(constant); console.log(Date.now()-t); }40 ms para matriz de 1 m, 450 ms para matriz de 10 m.