Skip to content

Instantly share code, notes, and snippets.

@jniac
Created April 29, 2021 09:22
Show Gist options
  • Save jniac/45224ceb0baf042b395eecaf45c017e3 to your computer and use it in GitHub Desktop.
Save jniac/45224ceb0baf042b395eecaf45c017e3 to your computer and use it in GitHub Desktop.
js bench
const map = new Map()
export const addToBench = (msg, cb) => {
if (typeof msg === 'function') {
msg = msg.name
}
const index = map.size
map.set(msg, {
index,
msg,
cb,
totalDuration: 0,
totalRunLoop: 0,
runCount: 0,
opByMs: 0
})
}
export const clearBench = () => map.clear()
const wait = delay => new Promise(r => setTimeout(r, delay))
const thousands = (x, sep = '_') => x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, sep)
export const runBench = async () => {
const NOOP = '(noop)' // "no operation" special case
addToBench(NOOP, () => {})
const runCount = map.size
const runDuration = 100 // ms
const runLoop = 1000
await wait(100)
const bundles = [...map.values()]
for (const bundle of bundles) {
bundle.totalDuration = 0
bundle.totalRunLoop = 0
bundle.runCount = 0
bundle.opByMs = 0
}
for (let runIndex = 0; runIndex < runCount; runIndex++) {
await wait(100)
console.log(`bench run #${runIndex} (${bundles.map(b => b.index).join(',')})`)
for (const bundle of bundles) {
await wait(100)
const { cb } = bundle
const t = Date.now()
let duration = 0
while (true) {
for (let i = 0; i < runLoop; i++) {
cb(i, runLoop)
}
bundle.totalRunLoop += runLoop
duration = Date.now() - t
if (duration > runDuration) {
break
}
}
bundle.runCount++
bundle.totalDuration += duration
}
// NOTE: important!
// order may have significant impact on performance
// so between each run change the order
bundles.unshift(bundles.pop())
}
for (const bundle of map.values()) {
bundle.opByMs = bundle.totalRunLoop / bundle.totalDuration
}
// remove noop
const noopBundle = map.get(NOOP)
map.delete(NOOP)
const faster = [...map.values()].sort((A, B) => B.opByMs - A.opByMs).shift()
const lines = []
lines.push(`bench (${runCount}/${runCount}):`)
for (const bundle of [...map.values(), noopBundle]) {
const { msg, opByMs } = bundle
const isFaster = bundle === faster
lines.push(` ${msg}:`)
lines.push(` ${isFaster ? 'FASTER!' : `x${(faster.opByMs / opByMs).toFixed(3)}`}`)
lines.push(` op/ms: ${thousands(opByMs.toFixed(2))}`)
lines.push(` ${thousands(bundle.totalRunLoop)} in ${bundle.totalDuration}ms`)
lines.push('')
}
console.log(lines.join('\n'))
}
import { addToBench, runBench } from './bench.js'
addToBench('un', () => [Math.random()])
addToBench('deux', () => [Math.random(), Math.random()])
addToBench('quatre', () => [Math.random(), Math.random(), Math.random(), Math.random()])
addToBench('huit', () => [Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()])
runBench()
@jniac
Copy link
Author

jniac commented Apr 29, 2021

output should be something like:

bench run #0 (0,1,2,3,4)
bench run #1 (4,0,1,2,3)
bench run #2 (3,4,0,1,2)
bench run #3 (2,3,4,0,1)
bench run #4 (1,2,3,4,0)
bench (5/5):
  un:
    FASTER!
    op/ms: 58_427.72
    29_506_000 in 505ms

  deux:
    x1.898
    op/ms: 30_778.22
    15_543_000 in 505ms

  quatre:
    x3.041
    op/ms: 19_211.88
    9_702_000 in 505ms

  huit:
    x5.502
    op/ms: 10_619.80
    5_363_000 in 505ms

  (noop):
    x0.501
    op/ms: 116_532.67
    58_849_000 in 505ms

@jniac
Copy link
Author

jniac commented Apr 29, 2021

beware that order may have significant impact :

with "huit" first:

addToBench('huit', () => [Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random(), Math.random()])
addToBench('un', () => [Math.random()])
addToBench('deux', () => [Math.random(), Math.random()])
addToBench('quatre', () => [Math.random(), Math.random(), Math.random(), Math.random()])
runBench()
bench (5/5):
  huit:
    x4.056
    op/ms: 11_245.54
    5_679_000 in 505ms

  un:
    FASTER!
    op/ms: 45_611.88
    23_034_000 in 505ms

  deux:
    x1.451
    op/ms: 31_431.68
    15_873_000 in 505ms

  quatre:
    x2.411
    op/ms: 18_916.83
    9_553_000 in 505ms

  (noop):
    x0.391
    op/ms: 116_546.53
    58_856_000 in 505ms

"un" runs 23_034_000 times (29_506_000 when being first) -> x0.78 slower (-22%!!!)
"huit" runs 5_679_000 times (5_363_000 when being last) -> x1.05 faster (+5%)

side effects of JS optimization i guess

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment