About a week has passed since the first version of Bun (v.0.1.x) was made publicly available. Introductory benchmarks are touting three-times the performance of Node and Deno for HTTP requests per second 🤯. In this article, Kris Zyp, a software engineer at HarperDB with decades of experience in the JavaScript open-source community, will share his test results and opinion of Bun.Â
Basic Bun Overview
Bun is an exciting new JavaScript runtime platform that is demonstrating some amazing performance capabilities. Bun is based on the JavaScriptCore (JSC) engine (the JavaScript engine used by Safari), and is written in Zig (which is ABI compatible with C/C++, has similar semantics and performance, but more explicit control of flow). Bun has been a one-man tour de force, developed over the last year at a breakneck pace by Jarred Sumners, availing extremely quick iteration. And this project has also distinguished itself in one key way: a fervent and relentless focus on unmatched performance.
This is a lofty goal considering what Bun is up against. Node.js is a ubiquitous JS runtime and for good reason. Node.js (and Deno) is founded on a remarkably efficient asynchronous event-driven I/O model and is built on the V8 JS engine. And it is worth remembering that V8 is an absolute engineering marvel, capable of taking the complex and dynamic language that is JavaScript and brilliantly combining bytecode generation, hidden classes, polymorphic inline caching, parallel garbage collection, and more advanced techniques to achieve levels of performance that go well beyond most dynamic high-level languages. The fact that Bun, and its JavaScriptCore engine, can even compete is impressive, and that it can outperform Nodejs in many ways is astonishing, not just within the JS community, but in the entire programming community.
Testing Bun
We are passionate about performance at HarperDB, which is why we have heavily leveraged the power of Node.js for our technology. And when Bun was first starting to receive some attention several months ago, I was eager to investigate. I was able to get early access and do some testing of some of the packages I maintain. Jarred was extremely helpful in getting Bun running, and we were able to collaborate on testing different aspects of Bun's performance. I also helped test the early NAPI implementation, since I work on a few libraries that heavily leverage NAPI, and built a test case for further improving NAPI compliance. There is great progress in being able to support high-performance native libraries directly in Bun.
Handle Bun with Care (For Now)
Undoubtedly Bun is going to be an important and exciting part of the JavaScript ecosystem. However, if you are interested in using Bun, it is wise to approach Bun with the right expectations. First, Bun is currently versioned at v0.1.4, as of this writing, which itself should set clear expectations: this is very early-release, pre-beta software. And while this is poised as an alternative to Node.js, you should not expect anything close to the same level of maturity and stability as Node.js right now. There are plenty of bugs, incomplete features, unsupported platforms, and even reliance on newer processor instructions that currently make it incompatible with older CPUs. This is still mainly one developer project, although contributors are growing rapidly. Releases are coming at an almost daily pace. Of course, this also means bugs are getting fixed at a rapid rate too! But expect regressions too.
Bun has done an amazing job of maximizing JavaScript compatibility with excellent support for CJS and ESM, as well as many shims for Node.js. However, you should certainly not expect all Node.js packages to work on Bun. There are plenty of extremely Node-specific functions that many packages use. And we shouldn’t expect these to all work; the community will be better off if packages upgrade to more standardized APIs than trying to replicate every Node eccentricity in every JS runtime.
And as mentioned before, it is important to remember that V8 really is and continues to be an incredibly performant JS engine. It would probably be unrealistic to expect that JSC can consistently outperform V8 in every form of JS usage. Each engineering team has made different design decisions with different optimizations and trade-offs. And in fact, you should expect V8 to still demonstrate better performance and efficiency in many situations. Consequently, evaluating the best future use cases for Bun requires understanding where it truly excels and does best. And I will try to share some of my testing observations to demonstrate the distinct performance profiles of Bun/JSC and Node.js/V8 to find the best potential for Bun.
Where Bun Excels
One of Bun’s primary advertised advantages is in HTTP processing. The home page readily advertises over three times the speed of Node.js with HTTP response rates. And this level of HTTP processing provides an immediate advantage for any web application server. Web frameworks are already rapidly springing up to take advantage of this.
Second, JSC has fantastic string handling performance. In most of my tests with encoding, decoding, slicing, and concatenating strings, JSC seemed to easily outperform V8. This is a tremendous advantage for many applications. One of Bun’s original primary goals was for JavaScript bundling where string manipulation is essential for performance, and indeed some of Bun’s earliest performance wins were in demonstrating remarkable bundling speeds. String performance is also key to server-side rendered (SSR) HTML web pages/applications. Generally, HTML is rendered through extensive string manipulation from templates and the combination of fast HTTP and string handling promises tremendous gains for SSR applications.
I also noticed that Bun seemed to be faster at updating object properties and array entries. This is an area where trade-offs seem to be in place: V8 seemed to be able to generate faster bytecode for quick access to properties (and consequently methods), which can often be heavily used in much application code. V8 also seems to generally be faster at iterating through properties (with a for-in loop). Bun also currently has a performance issue with async/promises, but will probably be resolved.
I have found plenty of other places where Bun/JSC outperforms V8, including Map usage, random numbers, garbage collection, and many native methods. But tests can vary widely, often Bun runs many times faster than Node.js for certain operations, and sometimes you might observe the complete reverse. Overall, I would expect most applications really will probably go faster on Bun, but testing your application will be important.
Finally, in comparing benchmarks, JSC and V8 actually seemed to be optimized for different CPU architectures. Not surprisingly, JSC seems to really outperform V8 more frequently on M1’s ARM architecture, whereas V8 tended to often do better on an x86 CPU.
A Greener Future?
While much of the attention on Bun has been focused on performance, perhaps the most potentially world-changing and revolutionary aspect of this combination of optimizations yields a fascinating synergy: Bun may be opening the doors for web applications with unmatched power/energy efficiency and lower costs. By being specifically optimized for ARM processors (with excellent power efficiency), and extremely low overhead HTTP and string processing capabilities, the next generation of ARM servers running Bun may be capable of handling many billions of web requests per kilowatt-hour; levels of green, low-energy server capabilities that would be extremely difficult to achieve with other technologies. In an age with disappointing levels of energy resources consumed by some software, this is an encouraging development with real and significant potential and value for humanity.
Hybrid Architectures
Most applications are probably not going to be in a position to immediately start running entirely on Bun in production. However, having multiple JavaScript runtimes available opens up a fascinating possibility: hybrid applications that can run both Node.js (or Deno) and Bun processes. This may sound unusual since most languages don’t have multiple runtimes to choose from, but this may be a unique opportunity for JS applications, leveraging different runtimes for different parts of the application that benefit from different capabilities, optimizations, and performance profiles.
This could also be a relatively easier transition than in other languages. JavaScript worker threads are already designed for very high levels of isolation, with no shared in-memory objects. While there is no interface for postMessage or SharedArrayBuffers between V8 and JSC, there are definitely solid mechanisms for interprocess communication using pipes, and even shared memory between processes using memory maps. Our own lmdb-js library provides a particular direct path for being able to share data between diverse processes with LMDB’s memory maps, which are used by HarperDB, with extremely high-speed data access/sharing potential. It is easy to imagine an application that uses Node.js to run packages that are heavily dependent on Node.js itself, storing data in an ultra-fast HarperDB instance, while also running Bun processes for handling incoming HTTP traffic and generating HTML directly from that same database instance in-process.
Conclusion
HarperDB will continue to provide stable and high-performance databases built on the capabilities and maturity of Node.js, and Bun’s NAPI implementation needs some fixes before we can use it. But we are excited about the future possibilities of potentially using Bun for future applications, and our software already has updates in place to leverage Bun’s fast FFI capabilities. Bun has demonstrated a remarkable trajectory, with constant improvements and optimizations, we are looking forward to leveraging them in the future, for the opportunity of both better performance and efficiency.
–----
About HarperDB
HarperDB’s integrated application + data platform is orders of magnitude faster and more flexible than last-generation alternatives. Easily replace SQL and NoSQL databases for cloud, edge, on-prem, peer-to-peer, and multi-deployment use cases. From validating an idea to delivering global scale, HarperDB grows with your application and saves you time and money every step of the way. Start for free today.