Header Ads Widget

Ticker

6/recent/ticker-posts

Prueba del rendimiento de JavaScript

 Tenía curiosidad por probar el rendimiento de JavaScript e investigué un poco al respecto.

Cuando hablo del rendimiento de JavaScript aquí, no me refiero a cosas como el tiempo hasta el primer byte, el tiempo hasta la interacción, etc. Estoy hablando de la velocidad de cálculo sin procesar: cuánto tiempo se ejecuta la función X en comparación con la función Y.

Descubrí que podemos usar dos métodos para probar el rendimiento: performance.nowDate.nowTenía curiosidad sobre la diferencia entre ellos, así que hice algunos experimentos para documentar mis hallazgos.

El procedimiento

El procedimiento para probar el rendimiento es sencillo. Hay tres pasos:

  1. Verifique la marca de tiempo actual
  2. Ejecuta algunas operaciones
  3. Verifique la marca de tiempo nuevamente

La diferencia entre las dos marcas de tiempo será la cantidad de tiempo necesaria para ejecutar las operaciones.

Así es como se ve este proceso en el código:

const start = performance.now()
// Do stuff 
const end = performance.now()

const elapsed = end - start
console.log(elapsed)

Performance.now vs Date.now

performance.nowse dice que genera una marca de tiempo Dom de alta resolución , lo que significa que será más precisa que Date.now.

Desafortunadamente, los navegadores tienen que completar esta marca de tiempo debido a problemas de seguridad, por lo que al final no hace mucha diferencia (según mis hallazgos).

Para ayudar con las pruebas, creé una perffunción.

function perf (message, callback, loops = 1) {
  const startTime = performance.now()
  while (loops) {
    callback()
    loops = loops - 1
  }
  const endTime = performance.now()
  const elapsed = endTime - startTime
  console.log(message, elapsed)
}

También creé un Date.nowequivalente y lo nombréperfDate

function perfDate (message, callback, loops = 1) {
  const startTime = Date.now()
  while (loops) {
    callback()
    loops = loops - 1
  }
  const elapsed = Date.now() - startTime
  console.log(message, elapsed)
}

Experimentos y hallazgos

Probé ambos performance.nowDate.nowcon una simple operación:

function test () {
  return 1 + 1
}

Mientras probaba, me di cuenta de que no tiene sentido probar una operación por dos razones.

Primero, performance.nowpuede medir operaciones en microsegundos pero Date.nowno puede. Entonces no podremos ver las diferencias entre ellos.

Tiempo necesario para una operación en Chrome

En segundo lugar, performance.nowse redondea al milisegundo más cercano en Safari y Firefox. Así que no tiene sentido comparar nada que tome menos de 1 ms.

Firefox redondea los valores de performance.now al milisegundo más cercano

Tuve que aumentar las pruebas a 10 millones de operaciones antes de que los números comenzaran a tener sentido.

10 millones de operaciones.

Hallazgo n. ° 1: Performance.now vs Date.now

Ejecuté este código:

const count = 10000000
perf('Performance', _ => { return 1 + 1 }, count)
perfDate('Performance', _ => { return 1 + 1 }, count)
Prueba inicial

Aquí, no encontré ninguna diferencia importante entre performance.nowDate.now.

Sin embargo, performance.nowparece más lento en Safari y Firefox. performance.nowtambién se redondea al milisegundo más cercano en Safari y Firefox.

Hallazgo n. ° 2: Chrome necesita tiempo para definir funciones

Intenté apilar perfperfDatefunciones para ver si había diferencias. Los resultados me sorprendieron.

const count = 10000000

perf('Performance', _ => { return 1 + 1 }, count)
perf('Performance', _ => { return 1 + 1 }, count)
perf('Performance', _ => { return 1 + 1 }, count)

perfDate('Date', _ => { return 1 + 1 }, count)
perfDate('Date', _ => { return 1 + 1 }, count)
perfDate('Date', _ => { return 1 + 1 }, count)
Prueba apilada.

Segunda y tercera prueba en Chrome para ambos perfperfDatesaltó de 8 ms a 80 ms. Eso es un aumento de 10 veces. ¡Pensé que estaba haciendo algo mal!

Descubrí que este aumento se debía a la definición de funciones sobre la marcha. Si utilicé una función predefinida, los números se redujeron a 8 ms.

function test () {
  return 1 + 1
}

const count = 10000000

perf('Performance', test, count)
perf('Performance', test, count)
perf('Performance', test, count)

perfDate('Date', test, count)
perfDate('Date', test, count)
perfDate('Date', test, count)
Resultados apilados cuando se usa una función predefinida.

Nota: También descubrí que Node's performance.nowtiene el mismo comportamiento que Chrome performance.now.

Hallazgo n. ° 3: es imposible obtener un resultado promedio

Me di cuenta de cada uno performance.nowDate.nowresultó en valores diferentes. Quería obtener un promedio de los resultados, así que agregué otro bucle a perf.

(Yo también hice lo mismo perfDate).

function perf (message, callback, loops = 1, rounds = 10) {
  const results = []

  while (rounds) {
    const startTime = performance.now()

    while (loops) {
      callback()
      loops = loops - 1
    }

    const endTime = performance.now()
    const elapsed = endTime - startTime

    results.push(elapsed)
    rounds = rounds - 1
  }

  const average = results.reduce((sum, curr) => curr + sum, 0) / results.length
  console.log(message)
  console.log('Average', average)
  console.log('Results', results)
}

Pero los resultados fueron extraños: el tiempo transcurrido para el segundo ciclo en adelante se redujo a cero. Esto sucedió para ambos perfperfDate.

¡También sucedió con los tres navegadores!

No estoy seguro de qué pasa aquí. Si sabes por qué, ¡dímelo!

Conclusión

Ambos performance.nowDate.nowse pueden utilizar para probar el rendimiento de JavaScript. Sin embargo, no hay una gran diferencia entre estos dos métodos.

Al realizar pruebas en Chrome, asegúrese de utilizar funciones predefinidas. No defina funciones sobre la marcha o obtendrá pruebas inexactas.

Publicar un comentario

0 Comentarios