A browser-based tool for speedy and correct JS performance comparisons!
- Minimalistic UI
- Code editor with IntelliSense
- All state is saved to URL - copy it and share with friends in no time!
- Automatically determines the number of iterations needed for a proper measurement — no hard-coding!
- Prevents dead code elimination and compile-time eval. optimizations from ruining your test!
- Verifies correctness (functions must compute the same value, be deterministic, depend on their inputs)
- Warms up functions before measuring (to give time for JIT to compile & optimize them)
Benchmarked functions are written as reducers, i.e. taking a previous value and returning some other value. The runtime executes your functions in a tight loop against some random initial value, saving the final value to a global variable (thus producing a side effect), so that no smart compiler could optimize out our computation!
So you must also provide a random initial value (not something like that) and ensure that your reducers follow some simple rules. Those rules are programmatically enforced — so you won't shoot yourself in the foot. Check the examples to get a sense of how to write a benchmark.
The rules:
-
The result of a function must depend on its input — and only on its input! You cannot return the same value again and again, or return some random values — there should be some genuine non-throwable computation on a passed input.
-
Given the same input, the output of the functions must be all the same. The comparison should be fair — we want to compare different implementations of exactly the same thing!
-
For..of loop over Object.values vs. Map.forEach (large integer keys)
-
..Add your own? Pull Requests are welcome!
In case you test functions operate on differently typed inputs, you might need to provide distinct initial values and provide a customized comparison function, otherwise it won't pass the soundness check. Here is an example:
benchmark('bigint vs number (addition)', {
initialValues() {
const seed = 1000000 + (Math.random() * 1000) | 0
return {
bigint: BigInt(seed),
number: seed,
}
},
equal(a, b) {
return BigInt(a) === BigInt(b)
}
}, {
bigint(prev) {
return prev + 1n
},
number(prev) {
return prev + 1
}
})