--file benchmark-report.json \
--err \
--github-actions ${{ secrets.GITHUB_TOKEN }} \
- "pnpm benchmark:tatami-ng:prod"
+ "pnpm benchmark:tinybench:prod"
{
"type": "node",
"request": "launch",
- "name": "Launch Tatami NG Benchmark Debug",
+ "name": "Launch Tinybench Benchmark Debug",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "pnpm",
- "runtimeArgs": ["run", "benchmark:tatami-ng:debug"],
+ "runtimeArgs": ["run", "benchmark:tinybench:debug"],
"skipFiles": ["<node_internals>/**"],
"stopOnEntry": true
}
To run the internal benchmark, you just need to navigate to the root of poolifier cloned repository and run:
-- `pnpm benchmark:tatami-ng`
+- `pnpm benchmark:tinybench`
### [Results](https://bencher.dev/perf/poolifier)
import { strictEqual } from 'node:assert'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import {
DynamicClusterPool,
}
}
-export const runPoolifierBenchmarkTatamiNg = async (
+export const runPoolifierBenchmarkTinyBench = async (
name,
workerType,
poolType,
poolSize,
- benchmarkReporter,
{ taskExecutions, workerData }
) => {
try {
+ const bench = new Bench()
const pool = buildPoolifierPool(workerType, poolType, poolSize)
+
for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
for (const enableTasksQueue of [false, true]) {
if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
for (const measurement of [Measurements.runTime, Measurements.elu]) {
- group(name, () => {
- bench(
- `${name} with ${workerChoiceStrategy}, with ${measurement} and ${
- enableTasksQueue ? 'with' : 'without'
- } tasks queue`,
- async () => {
- await runPoolifierPool(pool, {
- taskExecutions,
- workerData,
- })
- },
- {
- before: () => {
- pool.setWorkerChoiceStrategy(workerChoiceStrategy, {
- measurement,
- })
- pool.enableTasksQueue(enableTasksQueue)
- strictEqual(
- pool.opts.workerChoiceStrategy,
- workerChoiceStrategy
- )
- strictEqual(pool.opts.enableTasksQueue, enableTasksQueue)
- strictEqual(
- pool.opts.workerChoiceStrategyOptions.measurement,
- measurement
- )
- },
- }
- )
- })
- }
- } else {
- group(name, () => {
- bench(
- `${name} with ${workerChoiceStrategy} and ${
- enableTasksQueue ? 'with' : 'without'
- } tasks queue`,
+ const taskName = `${name} with ${workerChoiceStrategy}, with ${measurement} and ${
+ enableTasksQueue ? 'with' : 'without'
+ } tasks queue`
+
+ bench.add(
+ taskName,
async () => {
await runPoolifierPool(pool, {
taskExecutions,
})
},
{
- before: () => {
- pool.setWorkerChoiceStrategy(workerChoiceStrategy)
+ beforeAll: () => {
+ pool.setWorkerChoiceStrategy(workerChoiceStrategy, {
+ measurement,
+ })
pool.enableTasksQueue(enableTasksQueue)
strictEqual(
pool.opts.workerChoiceStrategy,
workerChoiceStrategy
)
strictEqual(pool.opts.enableTasksQueue, enableTasksQueue)
+ strictEqual(
+ pool.opts.workerChoiceStrategyOptions.measurement,
+ measurement
+ )
},
}
)
- })
+ }
+ } else {
+ const taskName = `${name} with ${workerChoiceStrategy} and ${
+ enableTasksQueue ? 'with' : 'without'
+ } tasks queue`
+
+ bench.add(
+ taskName,
+ async () => {
+ await runPoolifierPool(pool, {
+ taskExecutions,
+ workerData,
+ })
+ },
+ {
+ beforeAll: () => {
+ pool.setWorkerChoiceStrategy(workerChoiceStrategy)
+ pool.enableTasksQueue(enableTasksQueue)
+ strictEqual(
+ pool.opts.workerChoiceStrategy,
+ workerChoiceStrategy
+ )
+ strictEqual(pool.opts.enableTasksQueue, enableTasksQueue)
+ },
+ }
+ )
}
}
}
- const report = await run({ reporter: benchmarkReporter })
+
+ const tasks = await bench.run()
+ console.table(bench.table())
await pool.destroy()
- return report
+
+ const bmfResults = {}
+ for (const task of tasks) {
+ bmfResults[task.name] = {
+ latency: {
+ lower_value: task.result.latency.mean - task.result.latency.sd,
+ upper_value: task.result.latency.mean + task.result.latency.sd,
+ value: task.result.latency.mean,
+ },
+ throughput: {
+ lower_value: task.result.throughput.mean - task.result.throughput.sd,
+ upper_value: task.result.throughput.mean + task.result.throughput.sd,
+ value: task.result.throughput.mean,
+ },
+ }
+ }
+ return bmfResults
} catch (error) {
console.error(error)
}
import { writeFileSync } from 'node:fs'
import { env } from 'node:process'
import { parseArgs } from 'node:util'
-import { bmf } from 'tatami-ng'
import {
availableParallelism,
WorkerTypes,
} from '../../lib/index.mjs'
import { TaskFunctions } from '../benchmarks-types.cjs'
-import { runPoolifierBenchmarkTatamiNg } from '../benchmarks-utils.mjs'
+import { runPoolifierBenchmarkTinyBench } from '../benchmarks-utils.mjs'
const poolSize = availableParallelism()
const taskExecutions = 1
strict: true,
}).values.type
) {
- case 'tatami-ng':
+ case 'tinybench':
default:
- benchmarkReport = await runPoolifierBenchmarkTatamiNg(
+ benchmarkReport = await runPoolifierBenchmarkTinyBench(
'FixedThreadPool',
WorkerTypes.thread,
PoolTypes.fixed,
poolSize,
- bmf,
{
taskExecutions,
workerData,
)
benchmarkReport = {
...benchmarkReport,
- ...(await runPoolifierBenchmarkTatamiNg(
+ ...(await runPoolifierBenchmarkTinyBench(
'DynamicThreadPool',
WorkerTypes.thread,
PoolTypes.dynamic,
poolSize,
- bmf,
{
taskExecutions,
workerData,
}
benchmarkReport = {
...benchmarkReport,
- ...(await runPoolifierBenchmarkTatamiNg(
+ ...(await runPoolifierBenchmarkTinyBench(
'FixedClusterPool',
WorkerTypes.cluster,
PoolTypes.fixed,
poolSize,
- bmf,
{
taskExecutions,
workerData,
}
benchmarkReport = {
...benchmarkReport,
- ...(await runPoolifierBenchmarkTatamiNg(
+ ...(await runPoolifierBenchmarkTinyBench(
'DynamicClusterPool',
WorkerTypes.cluster,
PoolTypes.dynamic,
poolSize,
- bmf,
{
taskExecutions,
workerData,
import { randomInt } from 'node:crypto'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
/**
* Generates a random tasks map for benchmarking.
array[index2] = tmp
}
-group('Least used worker tasks distribution', () => {
- bench('Loop select', () => {
- loopSelect(tasksMap)
- })
- bench('Array sort select', () => {
- arraySortSelect(tasksMap)
- })
- bench('Quick select loop', () => {
- quickSelectLoop(tasksMap)
- })
- bench('Quick select loop with random pivot', () => {
- quickSelectLoopRandomPivot(tasksMap)
- })
- bench('Quick select recursion', () => {
- quickSelectRecursion(tasksMap)
- })
- bench('Quick select recursion with random pivot', () => {
- quickSelectRecursionRandomPivot(tasksMap)
- })
+const bench = new Bench()
+
+bench.add('Loop select', () => {
+ loopSelect(tasksMap)
+})
+bench.add('Array sort select', () => {
+ arraySortSelect(tasksMap)
+})
+bench.add('Quick select loop', () => {
+ quickSelectLoop(tasksMap)
+})
+bench.add('Quick select loop with random pivot', () => {
+ quickSelectLoopRandomPivot(tasksMap)
+})
+bench.add('Quick select recursion', () => {
+ quickSelectRecursion(tasksMap)
+})
+bench.add('Quick select recursion with random pivot', () => {
+ quickSelectRecursionRandomPivot(tasksMap)
})
-await run({ units: true })
+await bench.run()
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
/**
* Generates an array of worker indices.
return chosenWorker
}
-group('Round robin tasks distribution', () => {
- bench('Ternary off by one', () => {
- nextWorkerIndex = 0
- roundRobinTernaryOffByOne()
- })
- bench('Ternary with negation', () => {
- nextWorkerIndex = 0
- roundRobinTernaryWithNegation()
- })
- bench('Ternary with pre-choosing', () => {
- nextWorkerIndex = 0
- roundRobinTernaryWithPreChoosing()
- })
- bench('Increment+Modulo', () => {
- nextWorkerIndex = 0
- roundRobinIncrementModulo()
- })
+const bench = new Bench()
+
+bench.add('Ternary off by one', () => {
+ nextWorkerIndex = 0
+ roundRobinTernaryOffByOne()
+})
+bench.add('Ternary with negation', () => {
+ nextWorkerIndex = 0
+ roundRobinTernaryWithNegation()
+})
+bench.add('Ternary with pre-choosing', () => {
+ nextWorkerIndex = 0
+ roundRobinTernaryWithPreChoosing()
+})
+bench.add('Increment+Modulo', () => {
+ nextWorkerIndex = 0
+ roundRobinIncrementModulo()
})
-await run({ units: true })
+await bench.run()
+console.table(bench.table())
To run the internal benchmark, you just need to navigate to the root of poolifier cloned repository and run:
-- `pnpm benchmark:tatami-ng`
+- `pnpm benchmark:tinybench`
### [Results](https://bencher.dev/perf/poolifier)
"build:prod": "rollup --config",
"build:typedoc": "rollup --config --environment DOCUMENTATION,BUILD:development",
"build:analyze": "rollup --config --environment ANALYZE,BUILD:development",
- "benchmark:tatami-ng": "pnpm build && node --enable-source-maps benchmarks/internal/bench.mjs -t tatami-ng",
- "benchmark:tatami-ng:prod": "pnpm build:prod && node --enable-source-maps benchmarks/internal/bench.mjs -t tatami-ng",
- "benchmark:tatami-ng:debug": "pnpm build && node --enable-source-maps --inspect benchmarks/internal/bench.mjs -t tatami-ng",
+ "benchmark:tinybench": "pnpm build && node --enable-source-maps benchmarks/internal/bench.mjs -t tinybench",
+ "benchmark:tinybench:prod": "pnpm build:prod && node --enable-source-maps benchmarks/internal/bench.mjs -t tinybench",
+ "benchmark:tinybench:debug": "pnpm build && node --enable-source-maps --inspect benchmarks/internal/bench.mjs -t tinybench",
"test": "pnpm build --environment SOURCEMAP:false && cross-env NODE_ENV=test c8 mocha 'tests/**/*.test.mjs'",
"test:parallel": "pnpm build --environment SOURCEMAP:false && cross-env NODE_ENV=test c8 mocha --parallel 'tests/**/*.test.mjs'",
"test:debug": "pnpm build && cross-env NODE_ENV=test mocha --inspect 'tests/**/*.test.mjs'",
"rollup-plugin-delete": "^3.0.1",
"rollup-plugin-dts": "^6.2.3",
"sinon": "^21.0.0",
- "tatami-ng": "^0.8.18",
+ "tinybench": "^5.1.0",
"typedoc": "^0.28.14",
"typescript": "~5.9.3"
}
sinon:
specifier: ^21.0.0
version: 21.0.0
- tatami-ng:
- specifier: ^0.8.18
- version: 0.8.18(typescript@5.9.3)
+ tinybench:
+ specifier: ^5.1.0
+ version: 5.1.0
typedoc:
specifier: ^0.28.14
version: 0.28.14(typescript@5.9.3)
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
- tatami-ng@0.8.18:
- resolution: {integrity: sha512-Q22ZpW/yPXP1Hb4e2s1JQcTtoMaVHZLCt8AjAyBjARiXcorgHyvuWyIPFJOvmrTglXU2qQPLqL+7HEE0tIHdiA==}
- hasBin: true
- peerDependencies:
- typescript: ^5.4.3
-
tcomb-validation@3.4.1:
resolution: {integrity: sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==}
through@2.3.8:
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+ tinybench@5.1.0:
+ resolution: {integrity: sha512-LXKNtFualiKOm6gADe1UXPtf8+Nfn1CtPMEHAT33Fd2YjQatrujkDcK0+4wRC1X6t7fxUDXUs6BsvuIgfkDgDg==}
+ engines: {node: '>=20.0.0'}
+
tinyexec@1.0.1:
resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
tapable@2.3.0: {}
- tatami-ng@0.8.18(typescript@5.9.3):
- dependencies:
- peowly: 1.3.2
- typescript: 5.9.3
-
tcomb-validation@3.4.1:
dependencies:
tcomb: 3.2.29
through@2.3.8: {}
+ tinybench@5.1.0: {}
+
tinyexec@1.0.1: {}
tinyglobby@0.2.15: