probe.gl — Evaluación comparativa en Node.js

probe.gl

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 runBenchmarkscustomLogger 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)

probe.gl
Captura de pantalla de la consola

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:

Recent Post