-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { sleep } from './benchmark-utils.mjs'
} while (performance.now() < timeoutTimestampMs)
}
-group('Busy wait', () => {
- bench('dummyTimeoutBusyWait', () => {
- dummyTimeoutBusyWait(timeout)
- })
- bench('sleepTimeoutBusyWait', async () => {
- await sleepTimeoutBusyWait(timeout)
- })
- bench('divideAndConquerTimeoutBusyWait', async () => {
- await divideAndConquerTimeoutBusyWait(timeout)
- })
- bench('setIntervalTimeoutBusyWait', async () => {
- await setIntervalTimeoutBusyWait(timeout)
- })
-})
+const bench = new Bench({ name: 'Busy wait', time: timeout })
-await run({
- units: true,
+bench.add('dummyTimeoutBusyWait', () => {
+ dummyTimeoutBusyWait(timeout)
})
+bench.add('sleepTimeoutBusyWait', async () => {
+ await sleepTimeoutBusyWait(timeout)
+})
+bench.add('divideAndConquerTimeoutBusyWait', async () => {
+ await divideAndConquerTimeoutBusyWait(timeout)
+})
+bench.add('setIntervalTimeoutBusyWait', async () => {
+ await setIntervalTimeoutBusyWait(timeout)
+})
+
+await bench.run()
+console.table(bench.table())
import deepClone from 'deep-clone'
import clone from 'just-clone'
import _ from 'lodash'
-import { clone as rambdaClone } from 'rambda'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomObject } from './benchmark-utils.mjs'
const object = generateRandomObject()
-group(`Deep clone object with ${Object.keys(object).length} keys`, () => {
- bench('JSON stringify/parse', (obj = object) => {
+const bench = new Bench({
+ name: `Deep clone object (${JSON.stringify(object)})`,
+ time: 100,
+})
+
+bench
+ .add('JSON stringify/parse', (obj = object) => {
JSON.parse(JSON.stringify(obj))
})
- bench('structuredClone', (obj = object) => {
+ .add('structuredClone', (obj = object) => {
structuredClone(obj)
})
- bench('lodash cloneDeep', (obj = object) => {
+ .add('lodash cloneDeep', (obj = object) => {
_.cloneDeep(obj)
})
- bench('rambda clone', (obj = object) => {
- rambdaClone(obj)
- })
- bench('just-clone', (obj = object) => {
+ .add('just-clone', (obj = object) => {
clone(obj)
})
- bench('deep-clone', (obj = object) => {
+ .add('deep-clone', (obj = object) => {
deepClone(obj)
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
import deepMerge from 'deepmerge'
import _ from 'lodash'
-import { mergeDeepRight } from 'rambda'
-import { bench, group, run } from 'tatami-ng'
+import { merge as rambdaMerge } from 'rambda'
+import { Bench } from 'tinybench'
import { generateRandomObject } from './benchmark-utils.mjs'
const object = generateRandomObject()
const objectToMerge = generateRandomObject()
-group(
- `Deep merge two objects: object with ${
+const bench = new Bench({
+ name: `Deep merge two objects: object with ${
Object.keys(object).length
} keys, object with ${Object.keys(objectToMerge).length} keys`,
- () => {
- bench('lodash merge', (obj = object) => {
- _.merge(obj, objectToMerge)
- })
- bench('rambda mergeDeepRight', (obj = object) => {
- mergeDeepRight(obj, objectToMerge)
- })
- bench('deepmerge', (obj = object) => {
- deepMerge(obj, objectToMerge)
- })
- }
-)
-
-await run({
- units: true,
+ time: 100,
})
+
+bench
+ .add('lodash merge', (obj = object) => {
+ _.merge(obj, objectToMerge)
+ })
+ .add('rambda merge', (obj = object) => {
+ rambdaMerge(obj, objectToMerge)
+ })
+ .add('deepmerge', (obj = object) => {
+ deepMerge(obj, objectToMerge)
+ })
+
+await bench.run()
+
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomNumberArray } from './benchmark-utils.mjs'
const size = 10000
let testArray = generateRandomNumberArray(size)
-group(`Empty array with ${size} elements`, () => {
- bench('length = 0', () => {
+const bench = new Bench({
+ name: `Empty array with ${size} elements`,
+ time: 100,
+})
+
+bench
+ .add('length = 0', () => {
testArray.length = 0
})
- bench('pop loop', () => {
+ .add('pop loop', () => {
while (testArray.length > 0) {
testArray.pop()
}
})
- bench('splice', () => {
+ .add('splice', () => {
testArray.splice(0, testArray.length)
})
- bench('shift loop', () => {
+ .add('shift loop', () => {
while (testArray.length > 0) {
testArray.shift()
}
})
- bench('initialize', () => {
+ .add('initialize', () => {
testArray = []
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
const number = 30
fibonacciRecursionMemoization(num - 2, memo))
}
-group(`Fibonacci number ${number}`, () => {
- bench('fibonacciLoop', () => {
+const bench = new Bench({ name: `Fibonacci number ${number}` })
+
+bench
+ .add('fibonacciLoop', () => {
fibonacciLoop(number)
})
- bench('fibonacciLoopWhile', () => {
+ .add('fibonacciLoopWhile', () => {
fibonacciLoopWhile(number)
})
- bench('fibonacciRecursion', () => {
+ .add('fibonacciRecursion', () => {
fibonacciRecursion(number)
})
- bench('fibonacciRecursionMemoization', () => {
+ .add('fibonacciRecursionMemoization', () => {
fibonacciRecursionMemoization(number)
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.results)
import _ from 'lodash'
-import { isEmpty } from 'rambda'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomObject } from './benchmark-utils.mjs'
const object = generateRandomObject()
-group(`Is empty object with ${Object.keys(object).length} keys`, () => {
- bench('Reflect keys', (obj = object) => {
+const bench = new Bench({
+ name: `Is empty object with ${Object.keys(object).length} keys`,
+ time: 100,
+})
+
+bench
+ .add('Reflect keys', (obj = object) => {
return obj?.constructor === Object && Reflect.ownKeys(obj).length === 0
})
- bench('Keys iteration', (obj = object) => {
+ .add('Keys iteration', (obj = object) => {
if (obj?.constructor !== Object) return false
// Iterates over the keys of an object, if
// any exist, return false.
for (const _ in obj) return false
return true
})
- bench('Object keys', (obj = object) => {
+ .add('Object keys', (obj = object) => {
return obj?.constructor === Object && Object.keys(obj).length === 0
})
- bench('lodash isEmpty', (obj = object) => {
+ .add('lodash isEmpty', (obj = object) => {
_.isEmpty(obj)
})
- bench('rambda isEmpty', (obj = object) => {
- isEmpty(obj)
- })
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
-group('Is undefined', () => {
- bench('=== undefined', (value = undefined) => {
+const bench = new Bench({
+ name: 'Is undefined',
+ time: 100,
+})
+
+bench
+ .add('=== undefined', (value = undefined) => {
return value === undefined
})
- bench("typeof === 'undefined'", (value = undefined) => {
+ .add("typeof === 'undefined'", (value = undefined) => {
return typeof value === 'undefined'
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
const sampleObj = {
address: {
name: 'Sid',
}
-group('JSON stringify', () => {
- bench('JSON.stringify', () => {
- JSON.stringify(sampleObj)
- })
+const bench = new Bench({
+ name: 'JSON stringify',
+ time: 100,
})
-await run({
- units: true,
+bench.add('JSON.stringify', () => {
+ JSON.stringify(sampleObj)
})
+
+await bench.run()
+
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomNumberArray } from './benchmark-utils.mjs'
return values.sort((a, b) => b - a)[0]
}
-group(`Max from ${size} numbers`, () => {
- bench('Math.max', () => {
+const bench = new Bench({
+ name: `Max from ${size} numbers`,
+ time: 100,
+})
+
+bench
+ .add('Math.max', () => {
Math.max(...testArray)
})
- bench('loopMax', () => {
+ .add('loopMax', () => {
loopMax(testArray)
})
- bench('reduceTernaryMax', () => {
+ .add('reduceTernaryMax', () => {
reduceTernaryMax(testArray)
})
- bench('reduceMathMax', () => {
+ .add('reduceMathMax', () => {
reduceMathMax(testArray)
})
- bench('sortMax', () => {
+ .add('sortMax', () => {
sortMax(testArray)
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomNumberArray } from './benchmark-utils.mjs'
return values.sort((a, b) => a - b)[0]
}
-group(`Min from ${size} numbers`, () => {
- bench('Math.min', () => {
+const bench = new Bench({
+ name: `Min from ${size} numbers`,
+ time: 100,
+})
+
+bench
+ .add('Math.min', () => {
Math.min(...testArray)
})
- bench('loopMin', () => {
+ .add('loopMin', () => {
loopMin(testArray)
})
- bench('reduceTernaryMin', () => {
+ .add('reduceTernaryMin', () => {
reduceTernaryMin(testArray)
})
- bench('reduceMathMin', () => {
+ .add('reduceMathMin', () => {
reduceMathMin(testArray)
})
- bench('sortMin', () => {
+ .add('sortMin', () => {
sortMin(testArray)
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
import hashObject from 'hash-object'
import { hasher } from 'node-object-hash'
import hash from 'object-hash'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomObject } from './benchmark-utils.mjs'
const object = generateRandomObject()
-group(`Hash object with ${Object.keys(object).length} keys`, () => {
- bench('hash-object', (obj = object) => {
+const bench = new Bench({
+ name: `Hash object with ${Object.keys(object).length} keys`,
+ time: 100,
+})
+
+bench
+ .add('hash-object', (obj = object) => {
return hashObject(obj, { algorithm: 'sha256' })
})
- bench('node-object-hash', (obj = object) => {
+ .add('node-object-hash', (obj = object) => {
return hasher({ alg: 'sha256' }).hash(obj)
})
- bench('object-hash', (obj = object) => {
+ .add('object-hash', (obj = object) => {
return hash(obj, { algorithm: 'sha256' })
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
"node-object-hash": "^3.1.1",
"object-hash": "^3.0.0",
"rambda": "^11.1.0",
- "tatami-ng": "^0.8.18",
"tinybench": "^6.0.0",
"uuid": "^13.0.0"
},
rambda:
specifier: ^11.1.0
version: 11.1.0
- tatami-ng:
- specifier: ^0.8.18
- version: 0.8.18(typescript@5.9.3)
tinybench:
specifier: ^6.0.0
version: 6.0.0
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
-
tinybench@6.0.0:
resolution: {integrity: sha512-BWlWpVbbZXaYjRV0twGLNQO00Zj4HA/sjLOQP2IvzQqGwRGp+2kh7UU3ijyJ3ywFRogYDRbiHDMrUOfaMnN56g==}
engines: {node: '>=20.0.0'}
tapable@2.3.0: {}
- tatami-ng@0.8.18(typescript@5.9.3):
- dependencies:
- peowly: 1.3.2
- typescript: 5.9.3
-
tinybench@6.0.0: {}
tinyexec@1.0.2: {}
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
/**
*
})
}
-group('Promise handling', () => {
- bench('await promise', async () => {
+const bench = new Bench({
+ name: 'Promise handling',
+ time: 100,
+})
+
+bench
+ .add('await promise', async () => {
try {
return await asyncFunction()
} catch (e) {
console.error(e)
}
})
- bench('promise with then().catch()', () => {
+ .add('promise with then().catch()', () => {
asyncFunction()
.then(r => {
return r
})
.catch(console.error)
})
- bench('voided promise', () => {
+ .add('voided promise', () => {
// eslint-disable-next-line no-void
void asyncFunction()
})
- bench('mishandled promise', () => {
+ .add('mishandled promise', () => {
asyncFunction()
})
-})
-await run({
- units: true,
-})
+await bench.run()
+
+console.table(bench.table())
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('Quick select', () => {
- 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({ name: 'Quick select', time: 100 })
-await run({
- units: true,
+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 bench.run()
+console.table(bench.table())
import { randomInt } from 'node:crypto'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import {
secureRandom,
return Math.floor(secureRandomWithRandomValues() * (max + 1))
}
-group('Random Integer Generator', () => {
- bench('Secure random integer generator', () => {
- getSecureRandomInteger(maximum)
- })
- bench('Secure random with getRandomValues() integer generator', () => {
- getSecureRandomIntegerWithRandomValues(maximum)
- })
- bench('Crypto random integer generator', () => {
- randomInt(maximum)
- })
- bench('Math random integer generator', () => {
- getRandomInteger(maximum)
- })
-})
+const bench = new Bench({ name: 'Random Integer Generator', time: 100 })
-await run({
- units: true,
+bench.add('Secure random integer generator', () => {
+ getSecureRandomInteger(maximum)
+})
+bench.add('Secure random with getRandomValues() integer generator', () => {
+ getSecureRandomIntegerWithRandomValues(maximum)
+})
+bench.add('Crypto random integer generator', () => {
+ randomInt(maximum)
})
+bench.add('Math random integer generator', () => {
+ getRandomInteger(maximum)
+})
+
+await bench.run()
+console.table(bench.table())
import _ from 'lodash'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { generateRandomObject } from './benchmark-utils.mjs'
const object = generateRandomObject()
-group(`Shallow clone object with ${Object.keys(object).length} keys`, () => {
- bench('Spread', () => {
- return { ...object }
- })
- bench('Object assign', () => {
- return Object.assign({}, object)
- })
- bench('lodash clone', () => {
- _.clone(object)
- })
+const bench = new Bench({
+ name: `Shallow clone object with ${Object.keys(object).length} keys`,
+ time: 100,
})
-await run({
- units: true,
+bench.add('Spread', () => {
+ return { ...object }
})
+bench.add('Object assign', () => {
+ return Object.assign({}, object)
+})
+bench.add('lodash clone', () => {
+ _.clone(object)
+})
+
+await bench.run()
+console.table(bench.table())
import { randomUUID } from 'node:crypto'
-import { bench, group, run } from 'tatami-ng'
+import { Bench } from 'tinybench'
import { v4 as uuid } from 'uuid'
-group('UUIDv4 generator', () => {
- bench('randomUUID', () => {
- randomUUID()
- })
- bench('uuid', () => {
- uuid()
- })
-})
+const bench = new Bench({ name: 'UUIDv4 generator', time: 100 })
-await run({
- units: true,
+bench.add('randomUUID', () => {
+ randomUUID()
+})
+bench.add('uuid', () => {
+ uuid()
})
+
+await bench.run()
+console.table(bench.table())