probe.gl — Evaluación comparativa en Node.js
¿Está buscando evaluación comparativa en Node.js? Permítanme presentarles probe.gl: una colección de herramientas de depuración front-end de JavaScript creadas por Uber.
probe.gl es una colección de herramientas de depuración front-end de JavaScript creadas por Uber. probe.gl tiene una variedad de herramientas, pero hoy nos centraremos en Bench, una clase de arnés de evaluación comparativa que facilita la creación de “micro-benchmarks” con fines de optimización y pruebas de regresión.
En esta historia, crearemos una aplicación React de muestra que implementa la plataforma de evaluación comparativa probe.gl. Si desea encontrar más documentación sobre probe.gl, puede ir aquí.
Nota: Puede ver el resultado de los puntos de referencia en la parte inferior de esta historia.
Antes que empecemos
Antes de comenzar, quiero señalar que todo el código de esta historia se puede encontrar en GitHub aquí: probegl-benchmarking-sample.
Siéntase libre de usarlo en sus propios proyectos personales y profesionales y cámbielo para que se ajuste a sus necesidades.
Configuración
Para comenzar, creemos un nuevo proyecto React
Nota: estoy usando la versión de Node v18.12.0
npx create-react-app benchmark-react-app cd benchmark-react-app
A continuación, necesitaremos agregar probe.gl bench
a nuestro proyecto
npm install "@probe.gl/bench"
Funciones de muestra
A continuación, eliminemos las funciones de ejemplo. Vaya a App.js y cree las dos funciones de muestra que evaluaremos:
sample_function_sleep_async y sample_function_math_sqrt
La primera función duerme durante 100 milisegundos. La segunda función simplemente llama a la función integrada Math.sqrt.
async function sample_function_sleep_async() { const sleep = ms => new Promise( resolve => setTimeout(resolve, ms) ); await sleep(100); } function sample_function_math_sqrt() { Math.sqrt(100); }
Requisito previo
Antes de escribir nuestros puntos de referencia, debemos completar algunos requisitos previos. En este caso, necesitamos crear un archivo de ayuda probe.gl llamado ProbeGLHelper.js.
A primera vista, este archivo contiene mucho código, y tiene razón. Sin embargo, entro en gran detalle línea por línea describiendo todo lo que este archivo contiene más abajo.
// Helper variables const consoleTableClone = console.table; const LOG_ENTRY = { GROUP: 'group', TEST: 'test', COMPLETE: 'complete' }; // Helper function to customLogger(...) function convertItrsPerSecondToDecimal(itersPerSecond) { const value = parseFloat(itersPerSecond); const prefix = itersPerSecond[itersPerSecond.length - 3]; if (prefix === 'm') { return `${(value / 1000).toFixed(3)}/s`; } else { return itersPerSecond; } } // Helper function to customLogger(...) function getIterationRuntime(itersPerSecond) { const value = parseFloat(itersPerSecond); const prefix = itersPerSecond[itersPerSecond.length - 3]; let iterations = 0; switch (prefix) { case 'M': iterations = value * 1000000; break; case 'K': iterations = value * 1000; break; case 'm': iterations = value / 1000; break; default: iterations = value; break; } return ((1000 / iterations) / 1000).toFixed(8); } // Coefficient of variation let cv = {}; let testIndex = 0; export const customLogger = (result) => { const { entry, id, message, itersPerSecond, table, tests, priority, minIterations, time, delay, unit, error } = result; switch (entry) { case LOG_ENTRY.GROUP: // Commented code left here for reference // console.log(`Group: ${message}`); // console.log({ result }); break; case LOG_ENTRY.TEST: // Commented code left here for reference // console.log(`Test: `); // console.log({ result }); cv[testIndex++] = { 'cv': `±${(error * 100).toFixed(2)}%` } break; case LOG_ENTRY.COMPLETE: // Commented code left here for reference // console.log({ result }); console.log(`Total runtime for ${id}: ${time}.`); testIndex = 0; let benchmarkGroup; let customTable = {}; // Create a custom results table Object.keys(tests).forEach(key => { if (table.hasOwnProperty(key)) { customTable[testIndex] = { 'Benchmark Name': key, 'Execution Time': `${getIterationRuntime(table[key].iterations)}s`, 'Benchmark Group': benchmarkGroup, 'Benchmark Suite': result.id, 'Coefficient of Variation': cv[testIndex]["cv"], 'Iterations/s': convertItrsPerSecondToDecimal(table[key].iterations), '# Test Iterations': minIterations }; testIndex++; } else { benchmarkGroup = key; } }); // Print the custom results table consoleTableClone(customTable); break; default: } } export const runBenchmarks = async (benchSuite) => { // This makes sure that all async tests run once per iteration and not 10+ times by default let allTests = benchSuite.tests; Object.keys(allTests).forEach(key => { if (allTests[key].async) { allTests[key].opts._throughput = 1; } }); // Disable table outputs from probe.gl console.table = () => { } // Run benchmarks await benchSuite.run(); // Enable all table outputs after tests are complete console.table = consoleTableClone; }
Código de archivo auxiliar / ProbeGLHelper.js
Hay mucho que desempacar. Este archivo auxiliar contiene dos funciones principales: : customLogger
and runBenchmarks
. customLogger
se utiliza para registrar nuestros resultados de referencia. runBenchmarks
se utiliza para ejecutar nuestros puntos de referencia con más control. Repasemos ProbeGLHelper.js línea por línea.
Línea 1 a 7: estas son variables auxiliares utilizadas en ambas funciones auxiliares
Líneas 9 a 40: estas funciones dan formato a la salida de customLogger
con fines de legibilidad
Línea 47: esta línea reúne todas las variables que probe.gl devuelve de una prueba de evaluación comparativa
Líneas 49: cada vez que probe.gl ejecuta un punto de referencia, se llama a customLogger
y se activa esta declaración de cambio
Línea 59: En esta línea almacenamos el coeficiente de variación devuelto por probe.gl y lo almacenamos en una matriz llamada cv. Usamos esta matriz en nuestra tabla de resultados final en la línea 78
Líneas 61 a 90: esta sección se llama cuando probe.gl completa todas las pruebas comparativas. Aquí es donde customLogger
crea una tabla que se muestra en la consola
Nota: Puede ajustar la salida de sus resultados de referencia en las líneas 71 a 86
Líneas 95 a 112: esta sección nos ofrece más control sobre probe.gl cuando ejecutamos puntos de referencia. Por ejemplo, las líneas 96 a 102 le permiten cambiar la cantidad de pruebas asíncronas ejecutadas por iteración (de manera predeterminada, se ejecutarían 10 pruebas asíncronas por iteración. Aquí cambiamos eso a 1 ejecución de prueba asíncrona por iteración)
Crear puntos de referencia
Antes de escribir nuestros puntos de referencia, debemos agregar las siguientes declaraciones de importación en la parte superior de App.js
import React, { useEffect } from 'react'; import { Bench } from '@probe.gl/bench'; import { customLogger, runBenchmarks } from './ProbeGLHelper';
¡Finalmente, estamos listos para escribir algunos puntos de referencia! Comencemos por crear una función asíncrona llamada sample_benchmark.
Entro en gran detalle línea por línea describiendo todo lo que esta función contiene más abajo.
async function sample_benchmark() { const benchOptions = { id: "Suite Name", log: customLogger, minIterations: 3 }; const bench = new Bench(benchOptions); // Benchmark Group 1 bench.group("Group Name 1") .addAsync(null, 'sleep_async', async () => { await sample_function_sleep_async() }, null); // Benchmark Group 2 bench.group("Group Name 2") .add(null, 'math_sqrt', () => { sample_function_math_sqrt() }, null); // Run our helper function runBenchmark(...) await runBenchmarks(bench); }
Código de evaluación comparativa / sample_benchmark
Más para desempacar. ¡Esta función crea nuestros puntos de referencia! Repasemos sample_benchmark línea por línea.
Líneas 2 a 6: aquí es donde configuramos las opciones para Bench
, incluido nuestro customLogger
Línea 7: inicialice la clase de arnés de evaluación comparativa probe.gl, Bench
, pasandobenchOptions
como parámetro
Línea 10 (Mismo concepto para la línea 18): Cree un grupo que contendrá puntos de referencia específicos
Líneas 11 a 15 (el mismo concepto para las líneas 19 a 23): aquí le damos a nuestra prueba de referencia unapriority (optional)
, una id
, una function
que vamos a probar y una initFunction
(esto está en desuso, por lo que pasamos nulo)
Nota: Las firmas de funciones para add/addAsync son:
add(priority, id, testFunc, initFunc[Deprecated]) : Bench addAsync(priority, id, testFunc, initFunc[Deprecated]) : Bench
Línea 26: Pase bench
ta nuestra función auxiliar runBenchmarks
que creamos en nuestro archivo auxiliar. Esto ejecutará los puntos de referencia que hemos creado.
Ejecutar puntos de referencia
Ahora, en la aplicación de funciones, reemplace todo el código generado por defecto con el siguiente código.
function App() { useEffect(() => { sample_benchmark() }, []); return <div>Look in the development console to see your benchmark results!</div> }
Código de aplicación de función () / function_app
Para iniciar nuestra aplicación ejecuta el siguiente comando
npm run start
Cuando abra la consola de su navegador web, debería ver algo similar a la captura de pantalla a continuación (si no lo hace, actualice la página. El navegador a veces omite los registros de la consola en la carga de la primera página)
Implementó con éxito la evaluación comparativa en Node.js mediante probe.gl. Si tiene preguntas o desea ver un escenario de evaluación comparativa específico utilizando probe.gl, hágamelo saber.
Siéntase libre de dejar una respuesta si tiene algún problema o algo no está claro. ¡Feliz codificación y que Dios los bendiga!
Gracias por llegar hasta aquí, si encuentras esto útil no olvides aplaudir 👍🏼suscribirse para recibir más contenido.
Si le interesa, puede echar un vistazo a algunos de los otros artículos que he escrito recientemente sobre AWS y Laravel: