7,639 karma · joined February 4, 2011
https://bun.com
jobs@bun.sh
https://github.com/oven-sh/bun/blob/7d5f5ad7728b4ede521906a4...
We trust the self-reported size by gzip up to 64 MB, try to allocate enough space for all the output, then run it through libdeflate.
This is instead of a loop that decompresses it chunk-by-chunk and then extracts it chunk-by-chunk and resizing a big tarball many times over.
It’s usually only worth it after ~tens of megabytes, but vast majority of npm packages are much smaller than that. So if you can skip it, it’s better.
- isolated, pnpm-style symlink installs for node_modules
- catalogs
- yarn.lock support (later today)
- bun audit
- bun update —interactive
- bun why <pkg> helps find why a package is installed
- bun info <pkg>
- bun pm pkg get
- bun pm version (for bumping)
We will also support pnpm lockfile migration next week. To do that, we’re writing a YAML parser. This will also unlock importing YAML files in JavaScript at runtime.
There is a Windows-only bug in the isolated install mode blocking us from using isolated installs ourselves in the bun repo, and we need to fix that before we can release this.
If you want to try this early, you can run `bun upgrade --canary` and `bun install --linker=isolated` or put `install.linker = "isolated"` in bunfig.toml.
Isolated installs are a significant performance improvement on Windows (10x, sometimes 20x faster installs) and a minor positive or neutral performance impact on macOS and Linux. More importantly, they make using bun install in monorepos a lot more reliable by preventing dependencies from loading versions of other dependencies they did not specify in their own package.json.
Happy to answer any questions about Bun
If you're worried about binary size from features you don't use: the binary size cost of Bun.sql is less than 50 KB (you can check this yourself via the .linker-map file in the *-profile.zip builds of Bun or via https://bloaty-csv-reader.vercel.app which was a tool I wrote a little while ago to see how much space various features of Bun use)
If you're worried about runtime overhead, practically everything in Bun is lazily loaded. So if you never access Bun.sql or Bun.S3Client, it will not load it. And, even if it does load it, because we implement it in native code and worry about this a lot, it doesn't really cost much to load.
It's also some very well-written Zig code. We use some of the code for graphemes in Bun for `Bun.stringWidth`.
We honestly should've done the text-based lockfile awhile ago. The JSON parsing overhead was very obviously not the right tradeoff compared to the DX impact. But I'm happy with all the implementation tradeoffs it imposed (reallocation gets complicated)
Bun's HTTP server performs 51% faster before parallelism. Their benchmark is incorrect. They posted a correction, and their correction is also incorrect. Benchmarking correctly is hard, and we put a lot of effort into making sure our benchmarks are easily reproducible.
Bun v1.1.30: 283,386 requests per second (51% faster)
Deno v2.0.0: 187,359 requests per second
Deno v1.45.5: 185,522 requests per second
The following code:
let i = 0;
export default {
async fetch(request: Request): Promise<Response> {
return new Response(`Hello, world! ${i++}`);
},
};
Run with: oha -c 10 -n 10000000 --disable-compression http://localhost:{port}
This was tested on a Linux x64 machine running Debian 11 with a 32 core Intel i9-13900 CPU and 64GB of RAM. In this benchmark, the HTTP server runs on a single thread, so the CPU core count is not as relevant but still worth mentioning.If we increase the number of concurrent connections from 10 to 1,000 - Bun's HTTP server performs 267% faster.
Bun v1.1.30: 209,133 requests per second (267% faster)
Deno v2.0.0: 78,289 requests per second
Deno v1.45.5: 76,628 requests per second
Run with:
oha -c 1000 -n 10000000 --disable-compression http://localhost:{port}
Note that we add the --disable-compression for Deno's benefit here (as it does nothing for Bun right now)Have not yet spent enough time investigating their other benchmarks.
To get it out the door, ended up adding some patches to TinyCC to support .framework on macOS and fix a few things with dlopen and include paths. Also added support for parsing the deprecated attribute used in lots of Darwin headers. C parsers seem a lot simpler than JavaScript which is nice
Bun is an extremely context-heavy product and being IRL makes it a lot easier to help each other when we get stuck and explain things. I think if we half-heartedly did remote it would just be worse for everyone than being one extreme of either fully in-person or fully remote.
We chose fully in-person, but it would be so interesting to see the alternate timeline where we chose fully remote.
Bun is an open-source JavaScript tooling company focused on making programming simpler. Today, Bun is a JavaScript runtime designed to be a faster drop-in replacement for Node.js, along with an incredibly fast npm client, jest-compatible test runner, and JavaScript transpiler, minifier, and bundler.
We're hiring systems engineers to come to San Francisco and help us make JavaScript faster and more productive. This role will involve lots of open-source low-level systems work, mostly in Bun's GitHub repo - https://github.com/oven-sh/bun and also in a commercial hosting product.
Apply here: https://apply.workable.com/oven/j/A7A1388873/
Most of our code is in Zig and C++ and open-source. To see what we do every day, have a look at the recent pull requests.
It isn't accurate to say Bun is a JavaScript engine. We use JavaScriptCore as the engine, which is the same engine used by Safari (WebKit). The engine is responsible for running the code and a number of language APIs (Array, Object, Number, RegExp, etc). The runtime is responsible for things like I/O, filesystem access, the event loop, and implementing a very large number of non-language APIs and modules
Happy to answer any questions
We embed TinyCC for FFI, but TinyCC doesn't expose a way to read the types for exported symbols.
Currently, it looks like this:
import { dlopen, FFIType, suffix } from "bun:ffi";
// `suffix` is either "dylib", "so", or "dll" depending on the platform
// you don't have to use "suffix", it's just there for convenience
const path = `libsqlite3.${suffix}`;
const {
symbols: {
sqlite3_libversion, // the function to call
},
} = dlopen(
path, // a library name or file path
{
sqlite3_libversion: {
// no arguments, returns a string
args: [],
returns: FFIType.cstring,
},
},
);
console.log(`SQLite 3 version: ${sqlite3_libversion()}`);
It would be nicer if it was something like this: import {sqlite3_libversion as version} from "sqlite3.h" with {lib: "sqlite3"};
console.log(`SQLite 3 version: ${version()}`);
Would love to use Aro to do this in the futureWe spend many hours reading JavaScriptCore (the engine)’s code and when we wrote the code for Buffer and related APIs we spent a lot of time benchmarking and iterating on different approaches. A lot of performance work looks like this
It’s also possible you ran a package.json script that had the #!/usr/bin/env node shebang at the top, which Bun by default respects. You can force it to use bun by prefixing the command with “--bun”, like “bun --bun my-executable”
What error did you run into?
One of the things I’m happy about in our UDP sockets implementation is socket#sendMany. Internally, it uses sendmmsg on Linux and the undocumented sendmsg_x API on macOS which let you send multiple datagrams to multiple addresses in a single system call. Internally we do this automatically when reading messages (recvmmsg / recvmsg_x)
No, it’s because almost nobody has enough patience to upload a crash report for a GitHub issue. It has to be easy. Making it a URL that autofills the form with almost everything we need makes it easy. The size matters too, we didn’t want it to have downsides for our users, but the important thing is making this whole process really easy for the user so that enough developers actually upload crash reports.
No.