09 November 2022
Bun benchmark speed test. Is it worth moving to Bun from Node?
What’s your current JavaScript runtime, and why is it Node.js? But have you heard there’s a new solution in town? Bun is a native code bundler, transpiler, and task runner with a built-in npm client. The creators promised to fulfill our need for speed and prioritized Bun’s performance over all other features. In this article, I will show you how to start an existing Node.js project on this new JavaScript runtime and compare if Bun is really the fastest out there.
First things first, what is JavaScript runtime?
A runtime environment is where your program will be executed. You can do it:
- by JavaScript engine built-in browser (V8 developed by the Chromium Project for Google Chrome)
- on server environments (such as Node.js or Bun) which are de-facto implementations of a “browser” running on the server.
There are few Javascript runtimes on the market. As of writing this article, the top three look like this.
Node.js
Node.js – the most popular (by GitHub stars), the oldest, but above all “the first one”. Before Node, JS existed only in the browser, so we have a lot to be grateful for.
At The Software House, we run our JS applications on Node.js, as it’s an established JS execution environment. In fact, it’s the only one supported by AWS Lambda and GCP Functions.
If you’re here, you definitely know Node inside and out, so let’s move on.
Deno
In second place there is Deno. We’ve already made some attempts to try out Deno and we really gave it a chance. Unfortunately, we didn’t find it convincing enough to move to this still slightly immature JS runtime.
Read more about our Deno experiences:
But the fact was a fact – a competition appeared. We have been curious ever since if something else than Node.js and Deno would fulfill JS developers’ hopes for super fast JS applications.
And then Bun was baked in Oven!
What is Bun?
As of writing, the third place is occupied by fresh and crisp Bun – the newest and fastest-growing JS runtime. Bun attracted a lot of attention when it gained $7 million in funding in August 2022.
The entire Bun project focuses on performance and being an all-in-one tool (runtime, bundler, package manager, transpiler).
In the “traditional” Node.js, you need the combined power of a couple of tools to achieve the same goals: npm, Webpack, etc.
How is Bun supposed to be faster than Node?
Aiming to boost its performance, the Bun team wrote it from scratch in Zig, a low-level C alternative. The browser engine running JS code in Bun is based on JavaScript Core – the JS engine inside Safari that is considered faster than Node’s V8, the engine inside Chromium.
Bun ships and the development team claim it’s faster because of an enormous amount of time spent profiling, benchmarking, and optimizing things. The general theme: Zig’s low-level control over memory and lack of hidden control flow makes it so much easier to write fast software.
In summary, Bun creators claim that it serves 4 times more requests per second and packages are installed 30 times faster than by npm.
My time with Bun
After reading Bun creator’s assurances and community discussion, I thought “that’s some big claims”. I was curious if what they say is true. Is Bun really that fast? Actually faster than Node.js?
I’ve already seen a few benchmarks (and other tech solutions for that matter) that promised the world but hardly delivered, so I was not going to replace Node without any hard data. So I’ve done what’s needed to be done: install Bun and get the number with some performance testing.
Let’s move on to implementation.
How to run your Express app with Bun?
In order to test Bun, I used The Software House’s homemade (or should I rather say “officemade”) Express Boilerplate. This boilerplate is highly scalable and focuses on performance and best practices boilerplate code for Node.js and TypeScript apps.
If you want to start your Node.js projects even faster, here’s a detailed overview of the TSH-original boilerplate:
So, to run Bun you need to follow these steps:
$ curl https://bun.sh/install | bash
$ export BUN_INSTALL="$HOME/.bun"
$ export PATH="$BUN_INSTALL/bin:$PATH"
$ cd repo
$ cp docker-compose.override.yml.dist docker-compose.override.yml
$ cp .env.dist .env
$ bun i
$ bun run docker-build
$ bun run watch
$ bun run start
As you can see, runs with no changes.
Let’s compare Bun and Node!
1. Package installation time
The first test we’re running is package installation time. We did a simple test, to simulate real-life workflow.
- Npm run installed 1273 packages in 23 seconds,
- Bun run installed 1003 in 15,6 seconds.
🏆WINNER: BUN*
*Disclaimer: Bun indeed is 32% faster, but the execution time it’s not as fast as Bun’s creator promised
2. Docker image
The second thing to compare is building the first docker image.
🏆WINNER: NPM
Using Bun doesn’t seem to affect Docker image-building time.
3. App-builder
Test number three will check how Bun and npm deal with starting app-builder.
🏆WINNER: BUN
The difference is so minimal that there’s no reason to switch to Bun on purpose.
4. Application start time
The fourth thing we compare is the application start time.
🏆WINNER: BUN
…but again, the difference is negligible.
Now, the most important. Is Bun faster than Node?
Below, we’re testing simple get endpoint /health
The tool we use in this test is WRK – a modern HTTP benchmarking tool capable of generating significant load when run on a single multi-core CPU.
In these tests, we are using Node 16.15.0 and Bun 0.2.1.
Test 1. 10000 connections in 60 seconds with a variable number of threads
🏆WINNER: NODE
Okay, fair enough. How about we tweak it up a bit with different parameters?
10 threads in 60 seconds, with a variable number of connections
As you can see, depending on the number of connections and the number of threads the results are similar. But in most cases, Node.js is faster. So…
🏆WINNER: NODE
Should you move from Node to Bun? Probably not
I’ve got some good news and bad news.
The bad news: Bun is not going to be a drop-in replacement for Node anytime soon
For this article, I’ve used an existing Node.js application. I can tell you that it’s not worth running your stable Node app on Bun. Even though there’s massive potential and room for expansion – for now, it’s just too immature. Bun’s still new has no complete documentation, and various errors may occur during implementation. Also, I’m pretty sure that in the foreseeable future it won’t be useful in serverless solutions using AWS Lambda, or Google Cloud Functions (as of writing, Node.js is the only supported environment). It will take some time for Bun.js to grow and become a technology that we can use in commercial projects. At present, Bun’s tiny wins in speed tests won’t compensate for the time lost if you run into unexpected errors.
If you started a new self-hosted early-stage project you can use Bun.js from the beginning and optimize it for working with Bun. Then, sure – go for it!
A small consolation for the Bun team while they are probably improving their solution – you already have the sweetest logo in the game. Just look again at how cute it is!
The good news: Node.js will be forced to innovate
Now, Node.js has not only one but two potential rivals on the market. I bet the Node team will be more “motivated” to increase their product’s performance as much as they can.
I believe that these technologies will likely coexist in the ecosystem rather than one displacing the other, much like multiple JDK distributions have spawned in the Java world, one being chosen above another mostly for licensing reasons. But knowing the fast-changing world of JavaScript, soon a new technology will appear with the intention to take over the market.
Disclaimer: This article is based on Bun 0.7.3. However, the 1.0 version 1.0 has already been released, and benchmark results may vary.