jsrosetta

Standard library

Benchmarking

Node.js's tinybench compared to Go's testing.B, Rust's criterion, Swift's ContinuousClock, and Java's JMH for measuring function performance.

Minimum versions
Node.js ≥ 20Go ≥ 1.24Rust ≥ 1.86Swift ≥ 5.7Java ≥ 8
Verified on
Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1

Node.js code is an ES module: save it as .mjs or set "type": "module" in package.json.

Go has had built-in benchmarking in its testing package for a long time. Node.js has no integrated benchmark runner, so the example below uses tinybench — a small, dependency-free library with the same "add tasks to a suite, then run" idea. Rust has no stable benchmarking in std either (it only exists on the nightly channel), so it uses the criterion crate — which needs its own benches/ directory declared in Cargo.toml, not something that runs as a single file. Swift has no standard benchmarking library at all; the example below measures things itself with std's ContinuousClock — simple, but without the warm-up/statistics the other three languages get (see the note below). Java uses JMH (Java Microbenchmark Harness), the standard tool in the Java ecosystem for avoiding the measurement pitfalls JIT compilation causes.

Comparing recursion and a loop (Fibonacci)

import { Bench } from 'tinybench'
 
const bench = new Bench({ name: 'fib' })
 
bench
  .add('fib#recursion', () => {
    fibRec(10)
  })
  .add('fib#loop', () => {
    fibLoop(10)
  })
 
await bench.run()
 
console.log(bench.name)
console.table(bench.table())
 
function fibRec(n) {
  if (n <= 1) {
    return n
  }
 
  return fibRec(n-1) + fibRec(n-2)
}
 
function fibLoop(n) {
  let f = [0, 1]
  for (let i = 2; i <= n; i++) {
    f[i] = f[i-1] + f[i-2]
  }
  return f[n]
}
$ node examples/benchmark_test.js
# condensed from console.table(); ns/op numbers vary between runs
fib
fib#recursion   413.13 ns/op (avg)
fib#loop         44.75 ns/op (avg)
$ go test -bench=. -benchmem examples/benchmark_test.go
# trimmed goos/goarch/cpu header; ns/op and allocs vary between runs
BenchmarkFibRec-12       6266443   171.4 ns/op    0 B/op   0 allocs/op
BenchmarkFibLoop-12     56055340    20.10 ns/op   96 B/op  1 allocs/op
PASS
ok  	command-line-arguments	2.701s
$ cargo bench
# trimmed warm-up/outliers/throughput; numbers vary between runs
fib#recursion           time:   [142.51 ns 142.75 ns 142.99 ns]
fib#loop                time:   [24.489 ns 24.530 ns 24.565 ns]
$ swiftc -O main.swift -o main && ./main
fib#recursion   221ns/op
fib#loop        133ns/op
$ mvn clean install && java -jar target/benchmarks.jar FibBenchmark
# trimmed warm-up/Blackhole warning; Score/Error vary between runs
Benchmark             Mode  Cnt    Score   Error  Units
FibBenchmark.fibLoop  avgt    3    9.271 ± 0.343  ns/op
FibBenchmark.fibRec   avgt    3  133.513 ± 1.932  ns/op

Reference: github.com/miguelmota/golang-for-nodejs-developers#benchmarking