|
| 1 | +#!/usr/bin/env node |
| 2 | + |
| 3 | +import * as logger2 from '@ekino/logger' |
| 4 | +import { Suite } from '@jonahsnider/benchmark' |
| 5 | +import pino from 'pino' |
| 6 | +import * as winston from 'winston' |
| 7 | +import * as logger3 from '../lib/esm/index.js' |
| 8 | + |
| 9 | +const suite = new Suite('Logger Benchmark', { |
| 10 | + warmup: { trials: 3000 }, // Run benchmark for 3000ms |
| 11 | + run: { trials: 10_000 }, // Run 1000 warmup trials |
| 12 | +}) |
| 13 | + |
| 14 | +// Initialize loggers |
| 15 | +logger2.setLevel('info') |
| 16 | +logger3.setLevel('info') |
| 17 | + |
| 18 | +const ekinoLoggerV2 = logger2.createLogger('benchmark') |
| 19 | +const ekinoLoggerV3 = logger3.createLogger('benchmark') |
| 20 | +const pinoLogger = pino({ |
| 21 | + level: 'info', |
| 22 | + prettyPrint: false, |
| 23 | + destination: pino.destination({ sync: true }), // Synced JSON output |
| 24 | +}) |
| 25 | +const winstonLogger = winston.createLogger({ |
| 26 | + level: 'info', |
| 27 | + format: winston.format.json(), |
| 28 | + transports: [new winston.transports.Console()], |
| 29 | +}) |
| 30 | + |
| 31 | +const generateNestedObject = (numKeys, depth, currentDepth = 1) => { |
| 32 | + if (currentDepth > depth) return null |
| 33 | + |
| 34 | + const obj = {} |
| 35 | + for (let i = 0; i < numKeys; i++) { |
| 36 | + const key = `key_${currentDepth}_${i}` |
| 37 | + if (currentDepth === depth) { |
| 38 | + obj[key] = { |
| 39 | + stringValue: `string_${currentDepth}_${i}`, |
| 40 | + numberValue: i * 10, |
| 41 | + boolValue: i % 2 === 0, |
| 42 | + arrayValue: Array.from({ length: 3 }, (_, j) => `arrayItem_${j}`), |
| 43 | + } |
| 44 | + } else { |
| 45 | + obj[key] = generateNestedObject(numKeys, depth, currentDepth + 1) |
| 46 | + } |
| 47 | + } |
| 48 | + return obj |
| 49 | +} |
| 50 | + |
| 51 | +const message = 'This is a benchmark log message' |
| 52 | +const contextId = 'a037df3b-dbee-448e-9abb-8024d867ccc8' |
| 53 | +const logObject = generateNestedObject(5, 2) |
| 54 | + |
| 55 | +async function runBenchmarks() { |
| 56 | + suite |
| 57 | + .addTest('@ekino/logger v2.x', () => { |
| 58 | + ekinoLoggerV2.info(contextId, message, logObject) |
| 59 | + }) |
| 60 | + .addTest('@ekino/logger v3.x', () => { |
| 61 | + ekinoLoggerV3.info(contextId, message, logObject) |
| 62 | + }) |
| 63 | + .addTest('Winston', () => { |
| 64 | + winstonLogger.info(message, logObject) |
| 65 | + }) |
| 66 | + .addTest('Pino', () => { |
| 67 | + pinoLogger.info({ |
| 68 | + ctxId: contextId, |
| 69 | + ...logObject, |
| 70 | + message, |
| 71 | + }) |
| 72 | + }) |
| 73 | + |
| 74 | + const results = await suite.run() |
| 75 | + return results |
| 76 | +} |
| 77 | + |
| 78 | +const results = await runBenchmarks() |
| 79 | + |
| 80 | +const table = [...results] |
| 81 | + .map(([library, histogram]) => [ |
| 82 | + library, |
| 83 | + Math.round(1e9 / histogram.percentile(50)), // Median to ops/sec |
| 84 | + ]) |
| 85 | + .sort(([, a], [, b]) => b - a) |
| 86 | + .map(([library, opsPerSec]) => ({ |
| 87 | + library, |
| 88 | + 'ops/sec': opsPerSec.toLocaleString(), |
| 89 | + })) |
| 90 | + |
| 91 | +setTimeout(() => { |
| 92 | + console.table(table) |
| 93 | +}, 25000) |
0 commit comments