From 541e1267db338f9210482bcd59f835f53ebfc530 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Sun, 13 Oct 2024 21:51:25 -0300 Subject: [PATCH] src: add bench-node support and use by default --- README.md | 2 +- bench-it.js | 4 +- index.js | 2 +- package.json | 1 + src/babel-benchmark.js | 5 +- src/dotenv-benchmark.js | 2 +- src/lodash-benchmark.js | 11 +-- src/moment-benchmark.js | 11 +-- src/pino-benchmark.js | 2 +- src/prettier-benchmark.js | 6 +- src/typescript-benchmark.js | 145 ++++++++++++++++++------------------ src/underscore-benchmark.js | 11 +-- src/winston-benchmark.js | 2 +- worker.js | 40 +++++++++- 14 files changed, 148 insertions(+), 96 deletions(-) mode change 100644 => 100755 index.js diff --git a/README.md b/README.md index f06bb62..bc296d0 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ $ bench-it ./node To a pretty terminal output, run `index.js` ```console -$ node index.js +$ node --allow-natives-syntax index.js cpu: 13th Gen Intel(R) Core(TM) i5-13600K (20 cores) node: v20.13.1 (/home/hzk/.nvm/versions/node/v20.13.1/bin/node) os: Linux 5.15.133.1-microsoft-standard-WSL2 x64 diff --git a/bench-it.js b/bench-it.js index 4bc489f..973a77d 100755 --- a/bench-it.js +++ b/bench-it.js @@ -13,7 +13,7 @@ if (process.argv.length < 3) { const BINARY = process.argv[2]; if (process.argv[3] === "baseline") { - const result = execSync(`${BINARY} ${NODEJS_PACKAGE_BENCHMARK_PATH}/index.js`, { + const result = execSync(`${BINARY} --allow-natives-syntax ${NODEJS_PACKAGE_BENCHMARK_PATH}/index.js`, { env: { TTY: true }, }).toString(); fs.writeFileSync('baseline.out', `${result}`); @@ -34,7 +34,7 @@ try { diffCmd = "diff"; } -const currentResult = execSync(`${BINARY} ${NODEJS_PACKAGE_BENCHMARK_PATH}/index.js`, { +const currentResult = execSync(`${BINARY} --allow-natives-syntax ${NODEJS_PACKAGE_BENCHMARK_PATH}/index.js`, { env: { TTY: true }, }).toString(); fs.writeFileSync('current.out', currentResult); diff --git a/index.js b/index.js old mode 100644 new mode 100755 index 4019a3a..f804432 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env node --allow-natives-syntax const fs = require('node:fs/promises'); const path = require('node:path'); diff --git a/package.json b/package.json index 0a78af6..e194a19 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@types/lodash": "4.17.3", "@types/underscore": "1.11.15", "autocannon": "7.15.0", + "bench-node": "0.1.0", "dotenv": "16.4.5", "fastify": "4.26.1", "lodash": "4.17.21", diff --git a/src/babel-benchmark.js b/src/babel-benchmark.js index 6930039..330c4b5 100644 --- a/src/babel-benchmark.js +++ b/src/babel-benchmark.js @@ -1,5 +1,6 @@ const fs = require('node:fs'); const path = require('node:path'); +const assert = require('node:assert'); const Babel = require('@babel/standalone'); const payloads = [ @@ -16,6 +17,7 @@ module.exports = { let v = undefined; for (const p of payloads) { v = Babel.transform(p, { code: true, ast: true }).code; + assert.ok(v) } return v; }, @@ -25,7 +27,8 @@ module.exports = { fn: () => { let v = undefined; for (const p of payloads) { - v = Babel.transform(p, { code: false }).code; + v = Babel.transform(p, { code: false }); + assert.ok(v); } return v; }, diff --git a/src/dotenv-benchmark.js b/src/dotenv-benchmark.js index 6893817..9fd6a7e 100644 --- a/src/dotenv-benchmark.js +++ b/src/dotenv-benchmark.js @@ -14,5 +14,5 @@ module.exports = { }, }, ], - benchmarker: 'tinybench', + benchmarker: 'bench-node', }; diff --git a/src/lodash-benchmark.js b/src/lodash-benchmark.js index b961cc3..506908e 100644 --- a/src/lodash-benchmark.js +++ b/src/lodash-benchmark.js @@ -1,3 +1,4 @@ +const assert = require('node:assert'); const lodash = require('lodash'); module.exports = { @@ -7,19 +8,19 @@ module.exports = { { name: '.chunk', fn: () => { - lodash.chunk(['a', 'b', 'c', 'd'], 2); + assert.ok(lodash.chunk(['a', 'b', 'c', 'd'], 2)); }, }, { name: '.groupBy', fn: () => { - lodash.groupBy([6.1, 4.2, 6.3], Math.floor); + assert.ok(lodash.groupBy([6.1, 4.2, 6.3], Math.floor)); }, }, { name: '.includes', fn: () => { - lodash.includes({ 'a': 1, 'b': 2 }, 1); + assert.ok(lodash.includes({ 'a': 1, 'b': 2 }, 1)); }, }, { @@ -31,9 +32,9 @@ module.exports = { { 'user': 'fred', 'age': 40 }, { 'user': 'barney', 'age': 36 } ]; - lodash.orderBy(users, ['user', 'age'], ['asc', 'desc']); + assert.ok(lodash.orderBy(users, ['user', 'age'], ['asc', 'desc'])); } } ], - benchmarker: 'tinybench', + benchmarker: 'bench-node', }; diff --git a/src/moment-benchmark.js b/src/moment-benchmark.js index 89c2784..6b07934 100644 --- a/src/moment-benchmark.js +++ b/src/moment-benchmark.js @@ -1,3 +1,4 @@ +const assert = require('node:assert'); const moment = require('moment'); module.exports = { @@ -7,27 +8,27 @@ module.exports = { { name: 'format (full)', fn: () => { - return moment().format('MMMM Do YYYY, h:mm:ss a'); + assert.ok(moment().format('MMMM Do YYYY, h:mm:ss a')); }, }, { name: 'format', fn: () => { - return moment().format(); + assert.ok(moment().format()); }, }, { name: 'fromNow (YYYYMMDD)', fn: () => { - return moment('20111031', 'YYYYMMDD').fromNow(); + assert.ok(moment('20111031', 'YYYYMMDD').fromNow()); }, }, { name: 'subtract (10)', fn: () => { - return moment().subtract(10, 'days').calendar(); + assert.ok(moment().subtract(10, 'days').calendar()); }, }, ], - benchmarker: 'tinybench', + benchmarker: 'bench-node', }; diff --git a/src/pino-benchmark.js b/src/pino-benchmark.js index d0b59ec..ef1ea93 100644 --- a/src/pino-benchmark.js +++ b/src/pino-benchmark.js @@ -14,5 +14,5 @@ module.exports = { }, }, ], - benchmarker: 'tinybench', + benchmarker: 'bench-node', }; diff --git a/src/prettier-benchmark.js b/src/prettier-benchmark.js index 09595e6..0ca4e5d 100644 --- a/src/prettier-benchmark.js +++ b/src/prettier-benchmark.js @@ -1,5 +1,6 @@ const fs = require('node:fs'); const path = require('node:path'); +const assert = require('node:assert'); const prettier = require('prettier'); const payloads = [ @@ -15,7 +16,8 @@ module.exports = { fn: () => { let v = undefined; for (const p of payloads) { - v= prettier.format(p, { parser: 'babel' }); + v = prettier.format(p, { parser: 'babel' }); + assert.ok(v); } return v; }, @@ -29,6 +31,7 @@ module.exports = { p, { singleQuote: true, useTabs: true, parser: 'babel' }, ); + assert.ok(v); } return v; }, @@ -42,6 +45,7 @@ module.exports = { p, { semi: false, parser: 'babel' } ); + assert.ok(v); } return v; }, diff --git a/src/typescript-benchmark.js b/src/typescript-benchmark.js index eee757f..173f5a1 100644 --- a/src/typescript-benchmark.js +++ b/src/typescript-benchmark.js @@ -1,82 +1,85 @@ -const fs = require("node:fs"); -const ts = require("typescript"); -const path = require("node:path"); +const fs = require('node:fs'); +const ts = require('typescript'); +const path = require('node:path'); +const assert = require('node:assert'); -const filePath = path.join(__dirname, "..", "fixtures", "ts-sample.ts"); -const code = fs.readFileSync(filePath, "utf8"); +const filePath = path.join(__dirname, '..', 'fixtures', 'ts-sample.ts'); +const code = fs.readFileSync(filePath, 'utf8'); module.exports = { - name: "typescript", - type: "operation", - operations: [ - { - name: "transpile", - fn: () => { - ts.transpile( - code, - { - // CJS Settings - target: ts.ScriptTarget.ESNext, - module: ts.ModuleKind.CommonJS, - moduleResolution: ts.ModuleResolutionKind.Node, + name: 'typescript', + type: 'operation', + operations: [ + { + name: 'transpile', + fn: () => { + const r = ts.transpile( + code, + { + // CJS Settings + target: ts.ScriptTarget.ESNext, + module: ts.ModuleKind.CommonJS, + moduleResolution: ts.ModuleResolutionKind.Node, - // Avoid writing to disk - noEmit: true, + // Avoid writing to disk + noEmit: true, - // Avoids any checking related code - checkJs: false, - strict: false, - isolatedModules: true, - skipDefaultLibCheck: true, - skipLibCheck: true, - }, - filePath, - ); - }, - }, - { - name: "createSourceFile", - fn: () => { - ts.createSourceFile( - filePath, - code, - ts.ScriptTarget.ESNext, - false, - ts.ScriptKind.TS, - ); - }, - }, - { - name: "getSemanticDiagnostics", - fn: () => { - const program = ts.createProgram({ - rootNames: [filePath], - options: { - // CJS Settings - target: ts.ScriptTarget.ESNext, - module: ts.ModuleKind.CommonJS, - moduleResolution: ts.ModuleResolutionKind.Node, + // Avoids any checking related code + checkJs: false, + strict: false, + isolatedModules: true, + skipDefaultLibCheck: true, + skipLibCheck: true, + }, + filePath, + ); + assert.ok(r); + }, + }, + { + name: 'createSourceFile', + fn: () => { + const r = ts.createSourceFile( + filePath, + code, + ts.ScriptTarget.ESNext, + false, + ts.ScriptKind.TS, + ); + assert.ok(r); + }, + }, + { + name: 'getSemanticDiagnostics', + fn: () => { + const program = ts.createProgram({ + rootNames: [filePath], + options: { + // CJS Settings + target: ts.ScriptTarget.ESNext, + module: ts.ModuleKind.CommonJS, + moduleResolution: ts.ModuleResolutionKind.Node, - // also loads and checks js - allowJs: true, - checkJs: true, + // also loads and checks js + allowJs: true, + checkJs: true, - // test types - strict: true, + // test types + strict: true, - // Avoid writing to disk - noEmit: true, + // Avoid writing to disk + noEmit: true, - // Loads external files - isolatedModules: true, - skipDefaultLibCheck: false, - skipLibCheck: false, - }, - }); + // Loads external files + isolatedModules: true, + skipDefaultLibCheck: false, + skipLibCheck: false, + }, + }); - program.getSemanticDiagnostics(program.getSourceFile(filePath)); - }, - }, - ], - benchmarker: "tinybench", + program.getSemanticDiagnostics(program.getSourceFile(filePath)); + }, + }, + ], + benchmarker: 'tinybench', }; diff --git a/src/underscore-benchmark.js b/src/underscore-benchmark.js index 73c9cf8..2db79bc 100644 --- a/src/underscore-benchmark.js +++ b/src/underscore-benchmark.js @@ -1,4 +1,5 @@ const underscore = require('underscore'); +const assert = require('node:assert'); module.exports = { name: 'underscore', @@ -7,19 +8,19 @@ module.exports = { { name: '.chunk', fn: () => { - underscore.chunk(['a', 'b', 'c', 'd'], 2); + assert.ok(underscore.chunk(['a', 'b', 'c', 'd'], 2)); }, }, { name: '.groupBy', fn: () => { - underscore.groupBy([6.1, 4.2, 6.3], Math.floor); + assert.ok(underscore.groupBy([6.1, 4.2, 6.3], Math.floor)); }, }, { name: '.includes', fn: () => { - underscore.includes({ 'a': 1, 'b': 2 }, 1); + assert.ok(underscore.includes({ 'a': 1, 'b': 2 }, 1)); }, }, { @@ -31,9 +32,9 @@ module.exports = { { 'user': 'fred', 'age': 40 }, { 'user': 'barney', 'age': 36 } ]; - underscore.sortBy(users, ['user', 'age'], ['asc', 'desc']); + assert.ok(underscore.sortBy(users, ['user', 'age'], ['asc', 'desc'])); } } ], - benchmarker: 'tinybench', + benchmarker: 'bench-node', }; diff --git a/src/winston-benchmark.js b/src/winston-benchmark.js index 94878ad..591137a 100644 --- a/src/winston-benchmark.js +++ b/src/winston-benchmark.js @@ -22,5 +22,5 @@ module.exports = { }, }, ], - benchmarker: 'tinybench', + benchmarker: 'bench-node', }; diff --git a/worker.js b/worker.js index bb8ad44..874d54a 100644 --- a/worker.js +++ b/worker.js @@ -3,6 +3,7 @@ const assert = require('node:assert'); const autocannon = require('autocannon'); const { Bench } = require('tinybench'); +const { Suite } = require('bench-node'); const { setTimeout: delay } = require('node:timers/promises'); @@ -26,6 +27,36 @@ const runner = { aggregated[url].push(results) } }, + 'bench-node': async (opts, aggregated) => { + if (!aggregated.sortKey) { + aggregated.sortKey = 'opsSec' + } + + const suite = new Suite({ reporter: false }); + + for (const operation of opts.operations) { + suite.add(operation.name, operation.fn); + } + + const results = await suite.run(); + for (const result of results) { + if (!aggregated[result.name]) { + aggregated[result.name] = [{ + opsSec: result.opsSec, + samples: result.iterations, + sd: '', + variance: '', + }] + } else { + aggregated[result.name].push({ + opsSec: result.opsSec, + samples: result.iterations, + sd: '', + variance: '', + }) + } + } + }, tinybench: async (opts, aggregated) => { if (!aggregated.sortKey) { aggregated.sortKey = 'opsSec' @@ -78,10 +109,17 @@ const parser = { method: 'tinybench', operations: result, } + }, + 'bench-node': (settings, result) => { + return { + name: settings.name, + method: 'bench-node', + operations: result, + } } } -const ALLOWED_BENCHMARKER = ['autocannon', 'tinybench']; +const ALLOWED_BENCHMARKER = ['autocannon', 'tinybench', 'bench-node']; function asNumber (stat) { const result = Object.create(null)