Created
April 29, 2021 09:22
-
-
Save jniac/45224ceb0baf042b395eecaf45c017e3 to your computer and use it in GitHub Desktop.
js bench
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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')) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
beware that order may have significant impact :
with "huit" first:
"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