diff --git a/benchmarks/RESULTS.md b/benchmarks/RESULTS.md new file mode 100644 index 0000000..149aa61 --- /dev/null +++ b/benchmarks/RESULTS.md @@ -0,0 +1,67 @@ +# Zario Benchmark Results + +Results from running `npm run bench:high` (500,000 iterations/sample, 8 samples, 20% warmup). + +Environment: Node.js v24.14.1, `--expose-gc` + +--- + +## Sync Logging + +| Benchmark | Iter/sample | Warmup | Median ops/sec | Mean ops/sec | P95 ops/sec | Median ns/op | Median total (ms) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Simple message (sync) | 500,000 | 100,000 | 11,552,893 | 11,509,206 | 11,626,194 | 87 | 43.28 | +| Message with metadata (sync) | 500,000 | 100,000 | 10,572,753 | 10,538,822 | 10,653,341 | 95 | 47.29 | +| Message with deep metadata (sync) | 500,000 | 100,000 | 6,687,858 | 6,655,676 | 6,698,615 | 150 | 74.76 | + +## Filtered Logs (Early Exit) + +| Benchmark | Iter/sample | Warmup | Median ops/sec | Mean ops/sec | P95 ops/sec | Median ns/op | Median total (ms) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Filtered debug log (level=error) | 500,000 | 100,000 | 1,008,217,655 | 993,001,783 | 1,724,197,386 | 1 | 0.50 | +| Filtered info log (level=error) | 500,000 | 100,000 | 1,005,689,767 | 930,771,268 | 1,597,270,584 | 1 | 0.50 | + +## JSON Formatting + +| Benchmark | Iter/sample | Warmup | Median ops/sec | Mean ops/sec | P95 ops/sec | Median ns/op | Median total (ms) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Simple JSON log | 500,000 | 100,000 | 11,568,692 | 11,557,255 | 11,661,240 | 86 | 43.22 | +| JSON log with metadata | 500,000 | 100,000 | 10,543,431 | 10,419,380 | 10,687,100 | 95 | 47.43 | + +## Async Logging + +| Benchmark | Iter/sample | Warmup | Median ops/sec | Mean ops/sec | P95 ops/sec | Median ns/op | Median total (ms) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Simple message (async enqueue) | 500,000 | 100,000 | 5,079,084 | 5,067,134 | 5,096,529 | 197 | 98.44 | +| Message with metadata (async enqueue) | 500,000 | 100,000 | 4,987,750 | 4,915,549 | 5,008,323 | 200 | 100.25 | + +## Formatter Direct + +| Benchmark | Iter/sample | Warmup | Median ops/sec | Mean ops/sec | P95 ops/sec | Median ns/op | Median total (ms) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Format text (with metadata) | 500,000 | 100,000 | 2,181,644 | 2,179,942 | 2,189,498 | 458 | 229.19 | +| Format text (simple) | 500,000 | 100,000 | 3,790,382 | 3,784,413 | 3,806,556 | 264 | 131.91 | +| Format JSON (with metadata) | 500,000 | 100,000 | 931,265 | 929,513 | 939,866 | 1,074 | 536.90 | +| Format JSON (simple fast path) | 500,000 | 100,000 | 1,390,686 | 1,388,912 | 1,406,143 | 719 | 359.54 | + +## Child Logger + +| Benchmark | Iter/sample | Warmup | Median ops/sec | Mean ops/sec | P95 ops/sec | Median ns/op | Median total (ms) | +|---|---:|---:|---:|---:|---:|---:|---:| +| Child logger simple message | 500,000 | 100,000 | 10,453,676 | 10,445,592 | 10,480,180 | 96 | 47.83 | +| Child logger with metadata | 500,000 | 100,000 | 10,117,448 | 10,084,576 | 10,169,217 | 99 | 49.42 | + +--- + +## Running the Benchmarks + +```sh +# Standard benchmark (50k–200k iterations/sample) +npm run bench + +# High-iteration benchmark (500k iterations/sample, 8 samples) +npm run bench:high + +# Custom iterations/samples via environment variables +ZARIO_BENCH_ITERATIONS=1000000 ZARIO_BENCH_SAMPLES=10 npm run bench +``` diff --git a/benchmarks/logger.bench.ts b/benchmarks/logger.bench.ts index b089c9c..148190d 100644 --- a/benchmarks/logger.bench.ts +++ b/benchmarks/logger.bench.ts @@ -30,29 +30,23 @@ interface BenchmarkSummary { medianTotalMs: number; } -const DEFAULT_SYNC_CONFIG: BenchmarkConfig = { - iterations: 50_000, - warmupIterations: 10_000, - samples: 6, -}; - -const FILTERED_CONFIG: BenchmarkConfig = { - iterations: 200_000, - warmupIterations: 40_000, - samples: 6, -}; - -const DEFAULT_ASYNC_CONFIG: BenchmarkConfig = { - iterations: 20_000, - warmupIterations: 4_000, - samples: 6, -}; - -const FORMATTER_CONFIG: BenchmarkConfig = { - iterations: 80_000, - warmupIterations: 12_000, - samples: 6, -}; +const BENCH_ITERATIONS = Number(process.env["ZARIO_BENCH_ITERATIONS"] ?? 0); +const BENCH_SAMPLES = Number(process.env["ZARIO_BENCH_SAMPLES"] ?? 0); + +function makeConfig(baseIterations: number, baseWarmup: number): BenchmarkConfig { + const iterations = BENCH_ITERATIONS > 0 ? BENCH_ITERATIONS : baseIterations; + const warmupIterations = BENCH_ITERATIONS > 0 ? Math.floor(iterations * 0.2) : baseWarmup; + const samples = BENCH_SAMPLES > 0 ? BENCH_SAMPLES : 6; + return { iterations, warmupIterations, samples }; +} + +const DEFAULT_SYNC_CONFIG: BenchmarkConfig = makeConfig(50_000, 10_000); + +const FILTERED_CONFIG: BenchmarkConfig = makeConfig(200_000, 40_000); + +const DEFAULT_ASYNC_CONFIG: BenchmarkConfig = makeConfig(20_000, 4_000); + +const FORMATTER_CONFIG: BenchmarkConfig = makeConfig(80_000, 12_000); function maybeGC(): void { const gcFn = (globalThis as { gc?: () => void }).gc; diff --git a/package-lock.json b/package-lock.json index 0276770..699b117 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "zario", - "version": "0.5.0", + "version": "0.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "zario", - "version": "0.5.0", + "version": "0.8.0", "license": "MIT", "devDependencies": { "@eslint/js": "^9.39.1", @@ -21,6 +21,7 @@ "jest": "^30.2.0", "ts-jest": "^29.4.5", "tsup": "^8.5.1", + "tsx": "^4.21.0", "typescript": "^5.9.3", "typescript-eslint": "^8.49.0" }, @@ -4863,6 +4864,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.13.7", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz", + "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -7380,6 +7394,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/rollup": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", @@ -8399,6 +8423,26 @@ "node": ">= 12" } }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index fe0d2e6..8c3c7b5 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,8 @@ "dev": "tsup --watch", "test": "jest", "lint": "eslint src benchmarks --ext .ts --max-warnings=0", + "bench": "node --expose-gc --import tsx/esm benchmarks/logger.bench.ts", + "bench:high": "ZARIO_BENCH_ITERATIONS=500000 ZARIO_BENCH_SAMPLES=8 node --expose-gc --import tsx/esm benchmarks/logger.bench.ts", "prepublishOnly": "npm run build" }, "repository": { @@ -83,6 +85,7 @@ "jest": "^30.2.0", "ts-jest": "^29.4.5", "tsup": "^8.5.1", + "tsx": "^4.21.0", "typescript": "^5.9.3", "typescript-eslint": "^8.49.0" },