Skip to content

xpl/what-code-is-faster

Repository files navigation

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)

Try it online!

How Does It Work?

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:

  1. 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.

  2. 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!

Examples

Extended Configuration

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
  }
})