This is an unscientific comparison update from previous blog posts that compared Node and Bun, but didn't compare with Deno.

### Temperature conversion

From Converting Celsius to Fahrenheit round-up it compared a super simple script that just prints a couple of lines of text after some basic computation. If you include Deno on that run you get:

``````
❯ hyperfine --shell=none --warmup 3 "bun run conversion.js" "node conversion.js" "deno run conversion.js"
Benchmark 1: bun run conversion.js
Time (mean ± σ):      22.2 ms ±   2.1 ms    [User: 12.4 ms, System: 8.6 ms]
Range (min … max):    20.6 ms …  36.0 ms    136 runs

Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

...

Summary
bun run conversion.js ran
1.97 ± 0.35 times faster than deno run conversion.js
2.41 ± 0.39 times faster than node conversion.js
``````

Note that `bun run` and `deno run` both support `.ts` files whereas Node needs it to be `.js` (unless you use something like `--require @swc-node/register`). So in this benchmark, I let `bun run` and `deno run` use the `.js` version.

``````
❯ deno --version
deno 1.45.2 (release, x86_64-apple-darwin)
v8 12.7.224.12
typescript 5.5.2

❯ node --version
v20.14.0

❯ bun --version
1.1.21
``````

### Leibniz formula

In Leibniz formula for π in Python, JavaScript, and Ruby I wrote a simple program that computes the value of π using the Leibniz formula. It became a comparison of that code implementation in Python vs. Ruby vs. Node.

But let's redo the test with Bun and Deno too. Code was

``````
let sum = 0;
let estimate = 0;
let i = 0;
const epsilon = 0.0001;

while (Math.abs(estimate - Math.PI) > epsilon) {
sum += (-1) ** i / (2 * i + 1);
estimate = sum * 4;
i += 1;
}
console.log(
`After \${i} iterations, the estimate is \${estimate} and the real pi is \${Math.PI} ` +
`(difference of \${Math.abs(estimate - Math.PI)})`
);
``````

Running it once, it prints:

``````
❯ deno run pi.js
After 10000 iterations, the estimate is 3.1414926535900345 and the real pi is 3.141592653589793 (difference of 0.0000999999997586265)
``````

Running them becomes more of a measurement of how fast the programs start rather than how fast they run, but it's nevertheless and interesting to know too:

``````
❯ hyperfine --warmup 3 "node pi.js" "bun run pi.js" "deno run pi.js"
Benchmark 1: node pi.js
Time (mean ± σ):      54.9 ms ±   6.5 ms    [User: 42.6 ms, System: 11.3 ms]
Range (min … max):    50.2 ms …  83.9 ms    48 runs

Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

...

Summary
bun run pi.js ran
1.92 ± 1.01 times faster than deno run pi.js
2.37 ± 0.31 times faster than node pi.js
``````

### Conclusion

Both of these programs that I'm comparing with are super trivial and take virtually no time to run, once they've started. So it becomes more a test of warm-start performance. Alas, it's cool to see that both Deno and Bun make a better job of it here. Bun is almost 2x faster than Deno and 2.5x faster than Node.