jsrosetta

Thư viện chuẩn

Benchmark

tinybench của Node.js so với testing.B (Go), criterion (Rust), ContinuousClock (Swift) và JMH (Java) để đo hiệu năng hàm.

Phiên bản tối thiểu
Node.js ≥ 20Go ≥ 1.24Rust ≥ 1.86Swift ≥ 5.7Java ≥ 8
Đã chạy thử trên
Node.js 24.12.0Go 1.27.1Rust 1.98.1Swift 6.2.4Java 25.0.4.1

Code Node.js là ES module: lưu file .mjs hoặc đặt "type": "module" trong package.json.

Go có benchmark built-in trong package testing từ rất sớm. Node.js không có benchmark runner tích hợp, nên ví dụ dưới dùng thư viện tinybench — nhỏ gọn, không dependency, cùng ý tưởng "thêm task vào suite rồi chạy". Rust cũng không có benchmark ổn định trong std (chỉ có trên nightly), nên dùng crate criterion — đòi hỏi một thư mục benches/ riêng khai trong Cargo.toml, không chạy như một file đơn lẻ được. Swift không có thư viện benchmark chuẩn nào; ví dụ dưới tự đo bằng ContinuousClock của std — đơn giản nhưng không có warm-up/thống kê như ba ngôn ngữ kia (xem ghi chú). Java dùng JMH (Java Microbenchmark Harness), công cụ tiêu chuẩn trong hệ sinh thái Java để tránh các bẫy đo lường của JIT.

So sánh đệ quy và vòng lặp (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
# rút gọn từ console.table(); số ns/op thay đổi giữa các lần chạy
fib
fib#recursion   413.13 ns/op (avg)
fib#loop         44.75 ns/op (avg)
$ go test -bench=. -benchmem examples/benchmark_test.go
# đã bỏ phần header goos/goarch/cpu; ns/op và allocs thay đổi giữa các lần chạy
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
# đã bỏ phần warm-up/outliers/goodput; số liệu thay đổi giữa các lần chạy
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
# đã bỏ phần warm-up/cảnh báo Blackhole; Score/Error thay đổi giữa các lần chạy
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

Tham khảo: github.com/miguelmota/golang-for-nodejs-developers#benchmarking